最佳管理ProgressDialog从AsyncTask的方式方式、ProgressDialog、AsyncTask

2023-09-12 01:16:34 作者:半城繁华半城伤

我想使用的AsyncTask 在我的应用程序管理的一些业务逻辑。什么是使用的 onProgressUpdate(...)方法的最佳方式的AsyncTask 在sepa​​red文件中定义的(而不是作为innter类活动的) 我有两个想法: 1.最简单的方法:创建 ProgressDialog 活动(使用 onCreateDialog(...) 方法),并通过构造函数传递引用我的的AsyncTask 的子类(覆盖 onProgressUpdate(...)我的的AsyncTask 子类中)。这种解决方案的缺点是UI组件的使用内部业务逻辑code

FooTask1.java:

 公共类FooTask1扩展的AsyncTask<太虚,整型,太虚> {
私人ProgressDialog mProgressDialog;

公共FooTask1(ProgressDialog progressDialog){
    超();
    mProgressDialog = progressDialog;
}

@覆盖
保护无效doInBackground(空...未使用){
    //耗时的操作
    的for(int i = 0; I< = 100;我++){
        this.publishProgress(ⅰ);
        尝试 {
            视频下载(100);
        }赶上(例外五){}
    }
    返回null;
}

@覆盖
保护无效onProgressUpdate(整数...进度){
    mProgressDialog.setProgress(进展[0]);
}

@覆盖
保护无效onPostExecute(无效的结果){
    mProgressDialog.dismiss();
}
}
 

FooActivity1.java:

 公共类FooActivity1延伸活动{

  私有静态最终诠释DIALOG_PROGRESS_ID = 0;
  私人ProgressDialog mProgressDialog;

  @覆盖
  公共无效的onCreate(包savedInstanceState){
      super.onCreate(savedInstanceState);
      的setContentView(R.layout.main);

      的ShowDialog(DIALOG_PROGRESS_ID);
      新FooTask(mProgressDialog).execute();
  }

  @覆盖
  受保护的对话框onCreateDialog(INT ID){
      开关(ID){
          案例DIALOG_PROGRESS_ID:
             mProgressDialog =新ProgressDialog(本);
             mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
             mProgressDialog.setMessage(载入中...);
             mProgressDialog.setCancelable(假);
             返回mProgressDialog;
          默认:
             返回null;
      }
  }
}
 

2,更复杂的方式:覆盖的的AsyncTask onProgressUpdate(...)法里面的活动类:

FooTask2.java:

 公共类FooTask2扩展的AsyncTask<太虚,整型,太虚> {
@覆盖
保护无效doInBackground(空...未使用){
    //耗时的操作
    的for(int i = 0; I< = 100;我++){
        this.publishProgress(ⅰ);
        尝试 {
            视频下载(100);
        }赶上(例外五){}
    }
    返回null;
}
}
 
Android 异步任务 AsyncTask ProgressDialog

FooActivity2.java

 公共类FooActivity2延伸活动{

私有静态最终诠释DIALOG_PROGRESS_ID = 0;
私人ProgressDialog mProgressDialog;

/ **第一次创建活动时调用。 * /
@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.main);

    的ShowDialog(DIALOG_PROGRESS_ID);
    新FooTaskLoader()执行()。
}

@覆盖
受保护的对话框onCreateDialog(INT ID){
    开关(ID){
        案例DIALOG_PROGRESS_ID:
            mProgressDialog =新ProgressDialog(本);
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setMessage(载入中...);
            mProgressDialog.setCancelable(假);
            返回mProgressDialog;
        默认:
            返回null;
    }
}

私有类FooTaskLoader扩展FooTask2 {
    @覆盖
    保护无效onProgressUpdate(整数...进度){
        mProgressDialog.setProgress(进展[0]);
    }

    @覆盖
    保护无效onPostExecute(无效的结果){
        dismissDialog(DIALOG_PROGRESS_ID);
    }
}
}
 

解决方案

我宁愿孤立的业务逻辑的东西从AsyncTask的比活性隔离AsyncTask的。

在一般情况下,AsyncTask的具有非常特殊的设计和使用的情况下,在机器人应用的生命周期,即,运行一段时间在后台线程耗时的任务,一旦完成,更新活动的在UI线程图。这就是为什么它总是建议使用它作为一个内部类的活动的。

一个更面向对象的设计国际海事组织正在隔离和集中业务逻辑成一个POJO(可重用性)。对于可测试性,你可以做这样的事情: 1.定义一个接口IBusinessDAO 2.定义RealBusinessDAO实现IBusinessDAO 3.定义MockBusinessDAO实现IBusinessDAO 4.调用IBusinessDAO.foo();内AsyncTask.doInBackground()

有关单元测试你的业务逻辑,因为它是一个POJO,你可以用纯粹的JUnit编写测试用例。有时候,我们要测试的UI组件,我们并不真正关心企业如何背后的逻辑实现的,例如,我的业务逻辑连接到远程HTTP服务器下载一些JSON数据,我不想当我这样做,每次只要测试的UI布局,针对这种情况,我可以很容易地改变我的活动使用MockBusinessDAO(有点Spring的DI概念)是这样的:

 公共类MyActivity延伸活动{
  IBusinessDAO businessDAO;

  ......

  私有类MyAsyncTask扩展的AsyncTask<虚空,虚空,虚空> {
    ......

    保护无效doInBackground(空... PARAMS){
      businessDAO.foo();
    }
  }

  ......

  公共无效的onCreate(包savedInstanceState){
    如果(runInTest)
      businessDAO =新MockBusinessDAO();
    其他
      businessDAO =新RealBusinessDAO();

    新myAsyncTask()执行()。
  }


}
 

做这些的一些优点是: 1. AsyncTask的执行是容易的,干净的(在doInBacnground几行code()) 2.业务逻辑的实现是纯粹的POJO,提高可重用性。 3.绝缘测试业务逻辑和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.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);
    }
}
}

解决方案

I would rather isolate business logic stuff from AsyncTask than isolate AsyncTask from 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.

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()

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();
  }


}

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.

Hope that help.