【问题标题】:Async Task started and ended in different activities异步任务在不同的活动中开始和结束
【发布时间】:2011-11-22 18:37:41
【问题描述】:

我想实现以下行为,但我不确定如何:

  1. 用户开始活动
  2. Activity 启动 AsyncTask
  3. 用户执行了一些创建新活动的操作
  4. AsyncTask 完成并以某种方式将结果返回给新活动

有没有办法实现这种行为?

谢谢

【问题讨论】:

  • 使用Service 是答案,或者甚至可能是在第二个Activity 中注册的BroadcastReceiver

标签: android android-activity android-asynctask


【解决方案1】:

创建一个Service,它本身会产生自己的线程并进行后台处理。您可以将活动绑定到服务,以便在处理完成时回调活动。

【讨论】:

    【解决方案2】:

    我一直在使用 Chris 建议的变体:

    首先创建一个IntentService,这是最容易创建的Service。然后使用SharedPreferences 指示IntentService 的状态,并在Service 和Activities 之间共享值。您的 Activity 可以将自己注册为 OnSharedPreferenceChangeListener,以便了解您的 Service 何时完成工作和/或它关心的另一个 SharedPreference 已更改。

    使用IntentService,您只需覆盖onHandleIntent 方法。 onHandleIntent 中的所有内容都将在后台线程上运行。

    【讨论】:

      【解决方案3】:

      这是一种完全按照您的意愿行事的方法,假设结果是一个 int。您可以使用 parcelable 对象扩展此属性。或许,使用 Service 仍然是最好的选择。

      1) 创建一个名为 Result 的类,它是结果的包装器。它必须实现Parcelable 接口:

      public class Result implements Parcelable {
          private int result;
      
          public Result(int i) {
              super();
              result = i;
          }
      
          public void setResult(int result) {
              this.result = result;
          }
      
          public int getResult() {
              return result;
          }
      
          @Override
          public int describeContents() {
              return 0;
          }
      
          @Override
          public void writeToParcel(Parcel dest, int flags) {
              dest.writeInt(result);
          }
      
          public static final Parcelable.Creator<Result> CREATOR = new Parcelable.Creator<Result>() {
              public Result createFromParcel(Parcel in) {
                  return new Result(in);
              }
      
              public Result[] newArray(int size) {
                  return new Result[size];
              }
          };
      
          public Result(Parcel in) {
              result = in.readInt();
          }
      
      }
      

      2) 现在,您可以使用 Result 对象作为第一个活动的私有变量:

      public class FirstActivity extends Activity {
          private Result result;
      
          ....
      }
      

      3) 在您的 firstActivity 中,您可以使用如下代码启动 AsyncTask:

      new MyAsyncTask(result).execute();
      

      4) 你的 AsyncTask 可以这样制作:

      class MyAsyncTask extends AsyncTask<Void, Void, Void> { // you can modify types as you want
          Result result;
          public MyAsyncTask(Result result) {
              this.result = result;
          }
      
          ....
      
          public mySetResult() {
              result.setResult(...); //set your value
          }
      
          ....
      }
      

      5)当你启动第二个Activity时,你可以将你的结果对象传递给第二个Activity:

      Intent i = new Intent(getApplicationContext(), SecondActivity.class);
      i.putExtra("parc", result);
      startActivity(i);
      

      6) 最后,从第二个活动中,您可以使用以下代码获取结果:

      Result res = (Result) getIntent().getParcelableExtra("parc");
      

      关于parcelable对象的更多详细信息,可以查看Android Developer

      【讨论】:

      • 我知道很老的答案,但我认为这不是一个好的解决方案。如果我理解正确,目标是让 AsyncTask 在第一个活动中启动,然后在任务运行时启动第二个活动。这只会在任务完成后启动第二个活动。其次,parcelable 类是多余的,因为您可以将 int 粘贴到包裹中。
      【解决方案4】:

      Service 是一个组件,它允许某些代码在活动之外具有单独的生命周期,而无需与用户交互。正如其他人所提到的,这当然是要考虑的一种选择。如果你这样做,IntentService 是使工作异步的最简单方法。

      但是,您可以继续使用 AsyncTask 并添加一些代码来表示它“完成”。如果您的应用程序被终止,后台工作不再重要,并且如果用户离开应用程序,您可以在此工作完成之前终止您的应用程序。另一种看待这一点的方法是,如果 AsyncTask 的结果只对这两个活动中的一个/两个活动重要,而不是外部活动。这是需求与需要服务的重要区别,服务再次提供活动之外的生命周期。

      要传递数据,请查看this doc。有很多方法可以解决这个问题,但对于这种事情,我更喜欢伪单例方法。 (我不喜欢使用 SharedPreferences 来传递数据,因为坦率地说,我不认为这是该类的用途。我更喜欢这种伪单例方法而不是纯单例,因为它更易于测试。Android 到处都使用单例方法不过这个地方。)我会在 Application 对象中创建对某种 AsyncTask 注册器类的引用。由于可以从两个活动中访问 Application 对象,因此第一个可以向注册器注册您的 AsyncTask,而第二个可以获取该 AsyncTask 并注册以侦听是否尚未完成。

      【讨论】:

      • 了解单例方法(如 kabuko 的参考资料所述)对于“短期内的非持久性用户定义对象”非常理想,了解这一点很重要。否则,应考虑 SharedPreferences 和/或 SQLite 数据库。
      • 是的,AsyncTasks 完美地归类为“非持久性用户定义的短期对象”。实际上,即使对于持久数据,我也经常使用单例方法的变体,我只是做同样的事情,并让该类根据需要将其写入磁盘/DB/SharedPreferences。
      猜你喜欢
      • 2017-01-05
      • 1970-01-01
      • 2015-12-04
      • 1970-01-01
      • 2014-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多