2015-02-24 58 views
1

我有一個棘手的問題,就是將這些東西整合在一起。 示例:我想獲取用戶位置並使用經度和緯度值更新UI。因爲我堅持了MVC模式,我創建了一個單獨的類此任務(如LocationWorker),並實現了它,這個指南: http://developer.android.com/training/location/retrie ..Android,Async,CallBack和UI

問題:在這種情況下onConnected回調位於LocationWorker類並且無法與UI進行通信。我試圖在MainActivity類中實現onConnected callBack(也爲GoogleApiClient.ConnectionCallbacks添加實現),但是我得到一個錯誤(嘗試在空對象引用上調用虛方法'methodName')。看起來,在Worker實際完成所有工作之前執行回調(連接後它獲取用戶位置,但OnConnectedCallback在連接之後且有任何時間獲取任何數據之前被觸發)。

無論如何,這對我來說是一個巨大的問題,我應該如何使用異步任務並且能夠在異步任務完成時更新UI(並且不打破MVC)?

回答

0

在AsyncTask中有一個get(),它會在請求完成時觸發並返回您在創建AsyncTask時指定的RETURN TYPE。

eg : ImageGrabber extends AsyncTask<String, String, Bitmap> 

這裏的返回類型爲位圖

所以這裏有一個樣品給你,下面的字符串將包含的響應。

String jsonResponse = new JSONHelper().execute("http://example.com").get(); 
0

異步類:

//We can attach any object to the async class for result 
private class MyAsyncTask extends AsyncTask<Void,MyObject,MyObject >{ 


    @Override 
    protected MyObject doInBackground(Void... params) { 

     //Do the work to get your data 
     //this is done in a background thread 

     //prepare the result 

     //MyObject object = new MyObject(); 
     //object.setLong(LONG); 
     //object.setLang(LANG); 


     //You can pass the result here 
     //return object; 
     return null; 
    } 

    @Override 
    protected void onPostExecute(MyObject object) { 
     super.onPostExecute(object); 

     //Update UI 
     //this is done on the main thread 

     //access data from the Object result 
     //object.getLong(); 
     //object.getLang(); 
    } 
} 

您啓動異步類:

new MyAsyncTask().execute(); 
+0

好主意,儘管如果我使用描述的方法來獲取某個位置,我已經有了一個OnConnected回調方法。 所以,如果我理解正確,我需要的只是從OnConnected回調調用異步任務? (在這種情況下,異步任務準備好所有數據並將其返回到UI線程)。如果是,只需在MainActivity中實現一個OnConnected回調? – 2015-02-24 19:28:44

+0

回調是一個好方法是的,我同意。雖然你知道有很多選擇:) – 2015-02-24 19:31:07

+0

等待數據是否與回調一起來,沒有必要在異步中準備它,只用於可能會阻止用戶界面的異步 – 2015-02-24 19:33:18

0

如果你想簡化用戶界面和任何任務之間的通信,我建議使用這個框架來解耦來自UI的任務:Greenrobot's EventBus

事件總線就是你所有用最小的學習曲線完成你想要做的事情。使用作業隊列將使你的任務/工作更容易爲經理,並且重試和持久性的好處

public class LocationEvent { 
    private float lat, lng; 
    public LocationEvent(float lat, float lng) { this.lat=lat; this.lng=lng; } 
} 

MainActivity { 
    public void onStart() { 
    super.onStart(); 
    EventBus.getDefault().register(this); 
    } 

    public void onStop() { 
    EventBus.getDefault().unregister(this); 
    super.onStop(); 
    } 

    public void onEvent(LocationEvent event) { 
    // update user location 
    } 
} 

LocationWorker { 
    void doSomething() { 
    eventBus.post(new LocationEvent(lat, lng)); 
    } 
} 

相反的AsyncTask的: 您的UI會申請了您的任務發佈的事件。

看看Path's Android Priority Job Queue

0

EventBus看起來很有前途。

另一種選擇是使用意圖和廣播接收器。

例子:

在MainActivity.java:

@Override 
public void onResume() { 
    super.onResume(); 
    IntentFilter iFilter= new IntentFilter("updatelocation"); 
    iFilter.addAction("someOtherAction"); //if you want to add other actions to filter 
    this.registerReceiver(br, iFilter); 
} 

@Override 
public void onPause() { 
    this.unregisterReceiver(br); 
    super.onPause(); 
} 

private BroadcastReceiver br = new BroadcastReceiver() { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     String action = intent.getAction(); 
     if (action.equals("UpdateLocation")){ 

      //set these to member variables for later retrieval 
      double lat = intent.getExtras().getDouble("lat"); 
      double lon = intent.getExtras().getDouble("lon"); 

      this.runOnUiThread(mUpdateLocation); 
     } 
    } 

}; 

private final Runnable mUpdateLocation = new Runnable() { 

    @Override 
    public void run() { 
     //TODO: Update your UI here       
    } 
}; 

然後,在你LocationWorker類,當位置改變發送意圖。確保您在LocationWorker類中具有對應用程序上下文的引用。

看到這個職位:passing GPS coordinates to activity

//Make sure you have a reference to the application context 
    Intent updateLocation= new Intent(context, MainActivity.class); 
    updateLocation.setAction("UpdateLocation"); 
    updateLocation.putExtra("lon", xLocation.getLongitude()); 
    updateLocation.putExtra("lat", xLocation.getLatitude()); 
    context.sendBroadcast(i); 
0

使用new Asynctaskname.execute().get();就會使異步任務完成,然後再執行下一個。