我想使用AsyncTask
来管理我的应用程序中的一些业务逻辑。使用separed文件中定义的onProgressUpdate(...)
AsyncTask
方法的最佳模式是什么(不是Activity
的内部类)
我有两个想法:
1.最简单的方法:在ProgressDialog
中创建Activity
(使用onCreateDialog(...)
方法)并通过构造函数传递对AsyncTask
的子类的引用(在我的内部覆盖onProgressUpdate(...)
AsyncTask
子类)。此解决方案的缺点是在业务逻辑代码中使用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.更复杂的方式:覆盖onProgressUpdate(...)
类中AsyncTask
的{{1}}方法:
FooTask2.java:
Activity
FooActivity2.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;
}
}
答案 0 :(得分:13)
我宁愿从AsyncTask中隔离业务逻辑内容而不是从Activity中隔离AsyncTask。
一般来说,AsyncTask在Android应用程序生命周期中有一个非常具体的设计和用例,即在后台线程中运行一些耗时的任务,一旦完成,在UI线程中更新Activity的视图。这就是为什么总是建议将它用作Activity的内部类。
更多OO设计IMO正在将您的业务逻辑隔离并集中到POJO中(以实现可重用性)。为了测试性,您可以执行以下操作:
1.定义IBusinessDAO接口
2.定义RealBusinessDAO实现IBusinessDAO
3.定义MockBusinessDAO实施IBusinessDAO
4.致电IBusinessDAO.foo();在AsyncTask.doInBackground()
对于业务逻辑的单元测试,因为它是一个POJO,您可以使用纯JUnit编写测试用例。有时候我们想测试UI组件而我们并不关心底层业务逻辑是如何实现的,例如,我的业务逻辑连接到远程http服务器下载一些json数据,我不想每次都这样做我只是想要测试UI布局,对于这种情况,我可以轻松更改我的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.隔离测试业务逻辑和UI组件,提高可测试性。
希望有所帮助。
答案 1 :(得分:1)
第一个解决方案可能就是我如何处理它 - 这就是Android框架的方式。这个解决方案的一个扭曲(可能我将如何处理它,如果AsyncTask
无法适应Activity
- 类)我会传递Context
作为参数,而且然后实例化并在ProgressDialog
中显示onPreExecute
。
解决方案编号2基本上与将对话框创建为内部类相同 - 所以如果你选择这个,你也可以这样做。