从 AsyncTask 管理 ProgressDialog 的最佳方式 [英] Best way to manage the ProgressDialog from AsyncTask
问题描述
我想使用 AsyncTask
来管理我的应用程序中的一些业务逻辑.使用分离文件中定义的 AsyncTask
的 onProgressUpdate(...)
方法的最佳模式是什么(不是作为 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
类中覆盖AsyncTask
的onProgressUpdate(...)
方法:
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屋!