Android,Async,CallBack和UI

时间:2015-02-24 18:47:30

标签: java android android-asynctask callback

将这些事情整合在一起我有一个棘手的问题。 示例:我想获取用户位置并使用纬度和经度值更新UI。因为我坚持使用MVC模式,所以我已经为此任务创建了一个单独的类(例如LocationWorker)并按照本指南实现了它: http://developer.android.com/training/location/retrie ..

问题:在这种情况下,onConnected回调位于LocationWorker类中,无法与UI通信。我试图在MainActivity类中实现onConnected callBack(也为GoogleApiClient.ConnectionCallbacks添加实现),但是我得到一个错误(尝试在空对象引用上调用虚方法' methodName')。似乎在Worker实际完成所有工作之前执行了回调(在连接之后它获取用户位置,但OnConnectedCallback在连接之后以及在它有任​​何时间获取任何数据之前被触发)。

无论如何,对我来说这是一个很大的问题,我应该使用什么才能拥有异步任务,并且能够在完成异步任务时更新UI(并且不要破坏MVC)?

5 个答案:

答案 0 :(得分:0)

AsyncTask中有一个get(),它将在请求完成时触发,并返回您在创建AsyncTask时指定的RETURN TYPE。

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

这里的返回类型是Bitmap

所以这里有一个示例,下面的字符串将包含响应。

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

答案 1 :(得分: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();

答案 2 :(得分:0)

如果您想简化用户界面和任何任务之间的沟通,我建议您使用此框架将您的任务与用户界面分离:Greenrobot's EventBus

只需最少的学习曲线,您就可以通过事件总线完成您想要完成的任务。 您的UI将订阅您的任务发布的事件:

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将使您的任务/作业更容易管理,并具有重试和持久性的额外好处。

看看Path's Android Priority Job Queue

答案 3 :(得分: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);

答案 4 :(得分:0)

使用new Asynctaskname.execute().get();它将首先完成异步任务,然后执行下一个。