从 AsyncTask 管理 ProgressDialog 的最佳方式 [英] Best way to manage the ProgressDialog from AsyncTask

查看:16
本文介绍了从 AsyncTask 管理 ProgressDialog 的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 AsyncTask 来管理我的应用程序中的一些业务逻辑.使用分离文件中定义的 AsyncTaskonProgressUpdate(...) 方法的最佳模式是什么(不是作为 Activity 的内部类)我有两个想法:
1.最简单的方法:在Activity中创建ProgressDialog(使用onCreateDialog(...)方法),并将引用传给我的子类>AsyncTask 通过构造函数(在我的 AsyncTask 子类中覆盖 onProgressUpdate(...)).此解决方案的缺点是在业务逻辑代码中使用了 UI 组件.

I would like to use the AsyncTask for manage some business logic in my application. What is the best pattern for using the onProgressUpdate(...) method of AsyncTask defined in separed files (not as innter class of Activity) I have two ideas:
1. The simplest way: create ProgressDialog in Activity (using onCreateDialog(...) method) and pass reference to my subclass of AsyncTask by constructor (override onProgressUpdate(...) inside my AsyncTask subclass). The disadvantage of this solution is usage of UI components inside business logic code.

FooTask1.java:

public class FooTask1 extends AsyncTask<Void, Integer, Void> {
private ProgressDialog mProgressDialog;

public FooTask1(ProgressDialog progressDialog) {
    super();
    mProgressDialog = progressDialog;
}

@Override
protected Void doInBackground(Void... unused) {
    // time consuming operation
    for (int i=0; i<=100; i++) {
        this.publishProgress(i);
        try {
            Thread.sleep(100);
        } catch (Exception e) {}
    }
    return null;
}

@Override
protected void onProgressUpdate(Integer... progress) {
    mProgressDialog.setProgress(progress[0]);
}

@Override
protected void onPostExecute(Void result) {
    mProgressDialog.dismiss();
}
}

FooActivity1.java:

public class FooActivity1 extends Activity {

  private static final int DIALOG_PROGRESS_ID = 0;
  private ProgressDialog mProgressDialog;

  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      showDialog(DIALOG_PROGRESS_ID);
      new FooTask(mProgressDialog).execute();
  }

  @Override
  protected Dialog onCreateDialog(int id) {
      switch(id) {
          case DIALOG_PROGRESS_ID:
             mProgressDialog = new ProgressDialog(this);
             mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
             mProgressDialog.setMessage("Loading...");
             mProgressDialog.setCancelable(false);
             return mProgressDialog;
          default:
             return null;
      }
  }
}

2.更复杂的方法:在Activity类中覆盖AsyncTaskonProgressUpdate(...)方法:

2.The more sophisticated way: override the onProgressUpdate(...) method of AsyncTask inside the Activity class:

FooTask2.java:

public class FooTask2 extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... unused) {
    // time consuming operation
    for (int i=0; i<=100; i++) {
        this.publishProgress(i);
        try {
            Thread.sleep(100);
        } catch (Exception e) {}
    }
    return null;
}
}

FooActivity2.java

public class FooActivity2 extends Activity {

private static final int DIALOG_PROGRESS_ID = 0;
private ProgressDialog mProgressDialog;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    showDialog(DIALOG_PROGRESS_ID);
    new FooTaskLoader().execute();
}

@Override
protected Dialog onCreateDialog(int id) {
    switch(id) {
        case DIALOG_PROGRESS_ID:
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setMessage("Loading...");
            mProgressDialog.setCancelable(false);
            return mProgressDialog;
        default:
            return null;
    }
}

private class FooTaskLoader extends FooTask2 {
    @Override
    protected void onProgressUpdate(Integer... progress) {
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
        dismissDialog(DIALOG_PROGRESS_ID);
    }
}
}

推荐答案

我宁愿将业务逻辑与 AsyncTask 隔离,也不愿将 AsyncTask 与 Activity 隔离.

I would rather isolate business logic stuff from AsyncTask than isolate AsyncTask from Activity.

总的来说,AsyncTask在Android应用程序生命周期中有一个非常具体的设计和用例,即在后台线程中运行一些耗时的任务,一旦完成,在UI线程中更新Activity的视图.这就是为什么总是建议将其用作 Activity 的内部类的原因.

In general, AsyncTask has a very specific design and use case in Android application life cycle, that is, run some time consuming task in the background thread, once done, update Activity's view in UI thread. This is why it is always recommended to use it as a inner class of Activity.

更多面向对象的设计 IMO 正在将您的业务逻辑隔离并集中到 POJO(为了可重用性).为了可测试性,您可以执行以下操作:
1.定义一个接口IBusinessDAO
2. 定义 RealBusinessDAO 实现 IBusinessDAO
3. 定义 MockBusinessDAO 实现 IBusinessDAO
4. 调用 IBusinessDAO.foo();内部 AsyncTask.doInBackground()

A more OO design IMO is isolating and centralizing your business logic into a POJO (for reusability). For testability, you can do something like this:
1. Define an interface IBusinessDAO
2. Define RealBusinessDAO implements IBusinessDAO
3. Define MockBusinessDAO implements IBusinessDAO
4. Call IBusinessDAO.foo(); inside AsyncTask.doInBackground()

为了对您的业务逻辑进行单元测试,因为它是一个 POJO,您可以纯粹使用 JUnit 编写您的测试用例.有时我们想测试 UI 组件,我们并不关心底层的业务逻辑是如何实现的,例如,我的业务逻辑连接到远程 http 服务器下载一些 json 数据,我不想每次都这样做想要测试 UI 布局,对于这种情况,我可以像这样使用 MockBusinessDAO(某种 Spring 的 DI 概念)轻松更改我的活动:

For unit-test your business logic, as it is a POJO, you can use purely JUnit write your test case. Sometimes we want to test UI component and we don't really care how underlying business logic is implemented, for instance, my business logic connect to remote http server download some json data, I don't want to do this every time when I just want to test the UI layout, for this situation, I can easily change my Activity use MockBusinessDAO (sort of Spring's DI concept) like this:

public class MyActivity extends Activity {
  IBusinessDAO businessDAO;

  ... ...

  private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
    ... ...        

    protected void doInBackground(Void... params) {
      businessDAO.foo();
    }
  }

  ... ...

  public void onCreate(Bundle savedInstanceState) {
    if (runInTest)
      businessDAO = new MockBusinessDAO();
    else
      businessDAO = new RealBusinessDAO();

    new myAsyncTask().execute();
  }


}

这样做的一些优点是:
1.AsyncTask的实现简单干净(doInBacnground()中的几行代码)
2.业务逻辑实现纯POJO,提高复用性.
3、隔离测试业务逻辑和UI组件,提高可测试性.

Some advantages of doing these are:
1. AsyncTask implementation is easy and clean (several lines of code in doInBacnground())
2. Business logic implementation is purely POJO, improve reusability.
3. Isolation test business logic and UI component, improve testability.

希望有所帮助.

这篇关于从 AsyncTask 管理 ProgressDialog 的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆