使用 ProgressDialog 和 AsyncTask 避免样板文件?

Avoiding boilerplate with ProgressDialog and AsyncTask?

我有一个包含很多活动的应用程序,其中很多活动会点击各种 json 网络 API 来加载和显示数据。一个常见的模式类似于:

public class MyActivity extends Activity {
    public void OnCreate(Bundle savedInstanceState) {
        ...
        ProgressDialog pd = ProgressDialog.show( ... );

        // This is a custom API which wraps AsynkTask and calls my callback in onPostExecute
        DoWebThing(url, new Callback() {
            public void onSuccess(String json) {
                pd.dismiss();
                // Do other UI stuff with the json data
            }
        });
    }
}

这很好用,并且类似于您在 SO 和教程中找到的许多代码片段。问题是用户可以在后台进程处于 运行 时离开页面。在这种情况下,我收到有关泄漏视图(ProgressDialog)的 logcat 错误,然后当我关闭它或执行其他 UI 操作时我会崩溃。

我尝试在 onSuccess 中添加提前检查:

if (!pd.isShowing()) {
    return;
}

这修复了某些设备上的崩溃,但不是其他设备,我们仍然收到关于泄漏视图的 logcat 错误。

我已经尝试用 MyActivity.this.isFinishing() 替换 pd.isShowing() 检查,但这对任何事情都没有帮助(在我目前正在测试的设备上)。仍然出现 logcat 错误并崩溃。

我已尝试 MyActivity.this.isDestroyed(),它修复了崩溃,但仅适用于 SDK 17+,并且仍然出现 logcat 错误。

真正解决这个问题的唯一选择是让我的进度对话框成为一个成员变量并覆盖 OnDestroy():

ProgressDialog mPd;
@Override
protected void onDestroy() {
    super.onDestroy();
    if (mProgressDialog != null) {
        mProgressDialog.dismiss();
        mProgressDialog = null;
    }
}

现在在回调中我可以检查是否 mProgressDialog == null.

效果很好。没有崩溃,也没有关于泄漏视图的 logcat 错误。但这感觉像很多样板 - 我必须将进度对话框作为一个成员变量并覆盖 OnDestroy() 在我所有(许多)做背景工作的活动中。

我没有看到更好的选择,但在我开始更新大量活动之前需要第二个意见。

创建一个 Activity,比如 NetworkBaseActivity。在此 activity 中创建 ProgressDialog 并处理 onDestroy。还创建一个名为 showMyDialog()hideMyDialog() 的方法来显示和隐藏对话框(来自子类)。现在你所有做后台工作的活动只需要扩展这个 activity。要显示对话框调用 showMyDialog() 并隐藏它调用 hideMyDialog()

像这样:

public class NetworkBaseActivity extends AppCompatActivity{
    ProgressDialog myDialog;
    onCreate(Bundle bundle){
        // initialize myDialog
    }

    public void showDialog(){
       // show myDialog if not shown
    }
    public void hideDialog(){
      // hide myDialog if already shown
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mProgressDialog != null) {
        mProgressDialog.dismiss();
        mProgressDialog = null;
    }
}

public class YourActivity extends NetworkBaseActivity{

}

我将代码直接输入到 Whosebug 中,所以请原谅我的打字错误,但你明白了。