如何将长期运行异步runnable的结果传递给活动?

时间:2013-12-19 23:53:24

标签: android

活动会启动在后台线程中运行的长时间运行的异步任务。此后台任务应在完成时将结果返回给活动(例如,通知用户操作成功或失败)

结果可以随时到达。问题在于: - 可以销毁活动的原始实例对象(例如,旋转屏幕) - 没有现成活动(旧活动被破坏,新活动尚未开始) - 用户更改了可见活动(按下后退按钮,或按下主页按钮等)

请为此类技术任务提供设计模式。

2 个答案:

答案 0 :(得分:1)

  

结果可以随时到达。问题在于: - 活动的原始实例对象可能被破坏(例如,屏幕被旋转)

你可以实现一个轮换感知AsyncTask,如Mark Murphy(“CommonsWare”)here所述。

  

没有现成活动(旧活动被破坏,新活动尚未开始)

如果您的意思是因为onRetainNonConfigurationInstance()onCreate()之间的转换,请阅读上面的帖子,他解释了为什么这不应该是一个问题。

  

用户更改了可见活动(按下后退按钮,或按下主页按钮等)

否则,如果您的意思是Activities,长期数据加载,我相信您可以实现自己的Loader(例如,AsyncTaskLoader)并获得满意的结果,因为它们抽象了所有通常的生命周期你需要照顾的开销。

答案 1 :(得分:0)

有几种方法可以解决这个问题。

的AsyncTask:

public class AsyncTask<Void, Void, T extends Parcelable> {
   private final Context mApplicationContext;

   public MyAsyncTask(Context context) {
      mApplicationContext = context.getApplicationContext();
   }

   public void onPostExecute(T result) {
      Intent intent = new Intent(String.format("%s.DONE", mApplicationContext.getPackageName()));
      intent.putExtra("Data", result);
      mApplicationContext.sendBroadcast(intent);
   }
}

然后在你的活动中:

public class FooActivity extends Activity {
    BroadcastReceiver mReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent data) {

           if (TextUtils.equals(data.getAction(), String.format("%s.DONE", context.getPackageName()) {
               Object o = data.getParacelableExtra("DONE");
               // DO SOMETHING WITH IT
           }
         }

     };

    public void onCreate(Bundle b) {
       ...
       registerReceiver(mReceiver, new IntentFilter(String.format("%s.DONE", getPackageName())));
    }

    public void onDestroy() {
       ...
       unregisterReceiver(mReceiver);
    }

}

OR

试试这个:

public class MYActivity extends Activity implements MyCustomAsyncTask.Listener {

    private MyCustomAsyncTask<?, ?, ?> mTask;

    public Object onRetainNonConfigurationInstance() {
        if (mTask != null) {
            mTask.setListener(null);
        }
        return mTask;
    }


    public void onCreate(Bundle b) {
        mTask = getLastNonConfigurationInstance();
        if (mTask == null) {
            mTask = new MyCustomAsyncTask(....);
        }
        mTask.setListener(this);
    }

MyCustomAsyncTask

public class MyCustomAsyncTask<Void, Void, Object> extends AsyncTask {

      public interface Listener {
         public void doSomethingWithThis(Object o);
      }

      private mListener;

      public void setListener(Listener listener) {
           mListener = listener;
      }

      public void onPostExecute(Object result) {
          if (mListener != null) { 
             mListener.doSomethingWithThis(result);
          }
      }
...
}