需要一点帮助来理解这个 AsyncTask 场景

Need a little help understanding this AsyncTask scenario

我需要清楚地了解 AsyncTask 处理在我的场景中是如何发生的。我有一个普通的 java 对象,叫做 Donor

有一个 activity(比如说 DonorDetailActivity)修改了这个供体对象。修改发生在 AsyncTask<>(例如 DonorEditService)中。因此,从 DonorDetailActivity 调用 DonorEditService 在后台线程中编辑 Donor,并将结果发布到主要 UI 线程。

DonorDetailActivity class

public class DonorDetailActivity extends ActionBarActivity implements AsyncTaskCallback<Donor>{

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        btnEditDonor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) { //Invoke the DonorEditService
                    DonorEditService editService = new DonorEditService(DonorDetailActivity.this);
                    editService.execute(donor);
            }
        });
    }

    //Invoked from DonorEditService.onPostExecute(DonorBase updatedDonor)
    @Override
    public void onAsyncTaskCompleted(Donor updatedDonor) {
        updateUI(); //Refresh screen with updatedDonor
    }
}

所有这些更新的捐助者代码都可以正常工作。现在我的情况是用户可以向捐赠者拨打 phone 电话。在此过程中,我必须更新 Donor 字段以反映最后调用日期。为此,我可以看到两种方法。首先在后台线程中更新 Donor 然后启动一个 Phone Call Intent,或者先启动 Phone Call intent 然后更新 Donor。明智的代码如下

先更新再调用

//Update Donor
DonorEditService editService = new DonorEditService(activity);
donor.setLastCallDate(Calendar.getInstance().getTime());
editService.execute(donor);
//
Intent phoneIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + prefix + donor.getMobileNumber()));
activity.startActivity(phoneIntent);

先调用再更新

Intent phoneIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + prefix + donor.getMobileNumber()));
activity.startActivity(phoneIntent);
//Update Donor
DonorEditService editService = new DonorEditService(activity);
donor.setLastCallDate(Calendar.getInstance().getTime());
editService.execute(donor);
//

幸运或不幸的是,这两个都在模拟器上工作。唯一关心的是,如果调用 activity 不在 OnResume 状态,如何调用 AsyncTask.onPostExecute()。即它被Phone Call Activity 阻塞。另外,哪种方法更好;先编辑再调用;或先致电,然后编辑

编辑:

我刚刚从@Darwind 的评论中意识到我应该展示 DonorEditService 的代码,它实际上是 AsyncTask<DonorBase>(而不是 android Service)。 DonorBase 是 Donor 的超级 class。

这是 DonoEditService 代码的一部分

public class DonorEditService extends AsyncTask<DonorBase, Void, DonorBase> {
    public DonorEditService(Activity activity, boolean displayProgressDialog) {
        ...
    }

    @Override
    protected void onPreExecute() {
        //Show Progress Dialog for Donor Edit process
    }

    @Override
    protected DonorBase doInBackground(DonorBase... donors) {
        //Carry out the Http request to Edit Donor on Server
        ...
    }

    @Override
    protected void onPostExecute(DonorBase updatedDonor) {
        //Run on Main UI thread. I invoke AsyncTaskCallback from here
        taskCallback.onAsyncTaskCompleted(updatedDonor); //taskCallback is DonorDetailActivity implementing AsyncCallback
        ...
    }
}

好吧,您的问题有很多解决方案。

首先,我建议您不要将 DetailActivity 作为参数传递给 AsyncTask,因为这会导致泄漏。

起初我认为为您的目的使用 BroadcastReceiver 是个好主意,但后来发现这是行不通的,因为您离开 DetailActivity 并选择 phone打电话,最后可能收不到广播。

相反,我建议您实施 Service,因为您的 Activity 可以 bindunbindService 并询问有关的信息Service。这个想法是,即使用户导航离开您的 DetailActivity,您的 Service 也会 运行,因此可以保留一些数据,直到用户返回您的应用。

然后当用户返回到您的应用并恢复 DetailActivity 时,您只需要再次 "bind" 到 Service 并请求查看是否有任何更改用户不在。

您可以保留 AsyncTask 而不是让 DetailActivity 直接调用它,让 Service 直接调用它,这样 DetailActivity 调用 Service,这将调用 AsyncTask

现在我看到您已经为 DetailActivity 实施了一个 Observer pattern,以便在 AsyncTask 完成时得到通知。我实际上建议您实现 BroadcastReceiver 而不是这种 "hardly coupled" 观察者模式,因此 AsyncTask 会将 "broadcasts" 发送到 DetailActivity。现在,当 DetailActivity 暂停时(用户正在拨打 phone),广播将不会被 DetailActivity 接收,但这没关系。仅当用户将您的应用置于 100% 焦点(可见)时才应接收广播。

对不起,文字墙,但这有点像 "advanced" 主题。我希望它对你有帮助,如果没有,我会尝试用一些代码进行扩展:-)