从AsyncTaskpipe理ProgressDialog的最佳方法

我想在我的应用程序中使用AsyncTask来pipe理一些业务逻辑。 使用分离文件中定义的AsyncTaskonProgressUpdate(...)方法(不是Activity innter类)的最佳模式是什么?我有两个想法:
1.最简单的方法:在Activity创buildProgressDialog (使用onCreateDialog(...)方法)并通过构造函数(在AsyncTask子类中覆盖onProgressUpdate(...) )传递对AsyncTask的子类的引用。 这个解决scheme的缺点是在业务逻辑代码中使用UI组件。

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(...)方法:

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。

一般来说,AsyncTask在Android应用程序生命周期中有一个非常具体的devise和用例,就是在后台线程中运行一些耗时的任务,一旦完成,在UI线程中更新Activity的视图。 这就是为什么总是build议使用它作为Activity的内部类。

更多的面向对象devise的IMO将您的业务逻辑隔离并集中到一个POJO(可重用性)中。 为了可testing性,你可以做这样的事情:
1.定义一个接口IBusinessDAO
2.定义RealBusinessDAO实现IBusinessDAO
3.定义MockBusinessDAO实现IBusinessDAO
4.致电IBusinessDAO.foo(); 里面AsyncTask.doInBackground()

对于unit testing你的业务逻辑,因为它是一个POJO,你可以使用纯粹的JUnit编写你的testing用例。 有时候我们想testingUI组件,而且我们并不关心底层业务逻辑是如何实现的,例如,我的业务逻辑连接到远程http服务器下载一些json数据,我不想每次都只是这样做想要testingUI布局,对于这种情况,我可以很容易地改变我的Activity使用MockBusinessDAO(类似于Spring的DI概念),像这样:

 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.隔离testing业务逻辑和UI组件,提高可测性。

希望有所帮助。

  1. 第一个解决scheme可能是我如何处理它 – 这是Android框架的方式。 这个解决scheme的一个扭曲(如果AsyncTask不能适应Activity类),我可能会传递一个Context作为参数,然后实例化并在onPreExecute显示ProgressDialog

  2. 2号解决scheme基本上与创build内部类对话框相同 – 所以你可以这样做,如果你去这个。