为了使UI在数据获取时不僵死,数据获取需要在新开Worker线程中进行,然后将返回结果在UI线程中进行读取并渲染页面。面对这种异步处理,到底如何写才简洁,先后面临过三种实现方式。
首先是最原始的Java方式,new 一个Thread出来,将处理Runnable进去执行,执行完之后通过handler post到ui线程去更新界面。然后发现1.5后有了AsyncTask,非常好用,以后的项目中全部改成衍生出一个AsyncTask的子类,类中自然定义了运行前方法、运行中方法和运行后在ui中运行的方法。目前我做的项目中对AsyncTask做了封装,把它从原本的子类编写的过程,改成了函数调用方式,这就是目前正使用的第三种方法。
一个Android应用中,Activity通常可以建立以上层次关系。然后,在BaseActivity中对AsyncTask进行了封装,形成doAsync方法。方法体内创建一个新的AsyncTask并执行,由于AsyncTask是泛型参数,doAsync方法中传入的接口的参数也对应使用了泛型。至此,一个典型的异步调用的案例如下:
[java]
view plain
copy
1. this.doAsync(new
2. // 希望异步加载的数据
3. public String call() throws
4. String resu = NetworkTool.httpGetURL(
5. "http://www.baidu.com", "GBK");
6. return
7. }
8. new
9. // 当加载完成后回调,在UI线程中的操作
10. public void onCallback(final
11. if (null
12. tv_text1.setText(getRT().text1 + resu);
13. else
14. this);
15. }
16. }
17. });
这样,就从本来继承AsyncTask创建一个子类,然后初始化,然后运行的开发过程转变为了函数调用的过程。可以看到,调用可是简洁了很多!
为了实现它,我们附上BaseActivity中如下封装代码,需要说明的是这不是我的原创,我借鉴于Andengine引擎的实现代码进行的修改。
附源码:
[java]
view plain
copy
1. public class
2. public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final
3. null, false);
4. }
5. public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final
6. null, false);
7. }
8. public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final boolean
9. null, pCancelable);
10. }
11. public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback, final boolean
12. null, pCancelable);
13. }
14. public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final
15. false);
16. }
17. public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback, final
18. false);
19. }
20. public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback, final boolean
21. ActivityUtils.doAsync(pContext, pContext.getString(pTitleResID), pContext.getString(pMessageResID), pCallable, pCallback, pExceptionCallback, pCancelable);
22. }
23. public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback, final boolean
24. new
25. private
26. private Exception mException = null;
27. @Override
28. public void
29. this.mPD = ProgressDialog.show(pContext, pTitle, pMessage, true, pCancelable);
30. if(pCancelable) {
31. this.mPD.setOnCancelListener(new
32. @Override
33. public void onCancel(final
34. new
35. pDialogInterface.dismiss();
36. }
37. });
38. }
39. super.onPreExecute();
40. }
41. @Override
42. public T doInBackground(final
43. try
44. return
45. catch (final
46. this.mException = e;
47. }
48. return null;
49. }
50. @Override
51. public void onPostExecute(final
52. try
53. this.mPD.dismiss();
54. catch (final
55. "Error", e.toString());
56. }
57. if(this.isCancelled()) {
58. this.mException = new
59. }
60. if(this.mException == null) {
61. pCallback.onCallback(result);
62. else
63. if(pExceptionCallback == null) {
64. if (this.mException != null)
65. "Error", this.mException.toString());
66. else
67. this.mException);
68. }
69. }
70. super.onPostExecute(result);
71. }
72. null);
73. }
74. public static <T> void doProgressAsync(final Context pContext, final int pTitleResID, final ProgressCallable<T> pCallable, final
75. null);
76. }
77. public static <T> void doProgressAsync(final Context pContext, final int pTitleResID, final ProgressCallable<T> pCallable, final Callback<T> pCallback, final
78. new
79. private
80. private Exception mException = null;
81. @Override
82. public void
83. this.mPD = new
84. this.mPD.setTitle(pTitleResID);
85. this.mPD.setIcon(android.R.drawable.ic_menu_save);
86. this.mPD.setIndeterminate(false);
87. this.mPD.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
88. this.mPD.show();
89. super.onPreExecute();
90. }
91. @Override
92. public T doInBackground(final
93. try
94. return pCallable.call(new
95. @Override
96. public void onProgressChanged(final int
97. onProgressUpdate(pProgress);
98. }
99. });
100. catch (final
101. this.mException = e;
102. }
103. return null;
104. }
105. @Override
106. public void onProgressUpdate(final
107. this.mPD.setProgress(values[0]);
108. }
109. @Override
110. public void onPostExecute(final
111. try
112. this.mPD.dismiss();
113. catch (final
114. "Error", e.getLocalizedMessage());
115. /* Nothing. */
116. }
117. if(this.isCancelled()) {
118. this.mException = new
119. }
120. if(this.mException == null) {
121. pCallback.onCallback(result);
122. else
123. if(pExceptionCallback == null) {
124. "Error", this.mException.getLocalizedMessage());
125. else
126. this.mException);
127. }
128. }
129. super.onPostExecute(result);
130. }
131. null);
132. }
133. public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final AsyncCallable<T> pAsyncCallable, final Callback<T> pCallback, final
134. final
135. new
136. @Override
137. public void onCallback(final
138. try
139. pd.dismiss();
140. catch (final
141. "Error", e.getLocalizedMessage());
142. /* Nothing. */
143. }
144. pCallback.onCallback(result);
145. }
146. }, pExceptionCallback);
147. }
148.
149. public static class CancelledException extends
150. private static final long
151. }
152. }
[java]
view plain
copy
1. public interface
2. // ===========================================================
3. // Final Fields
4. // ===========================================================
5. // ===========================================================
6. // Methods
7. // ===========================================================
8. /**
9. * Computes a result asynchronously, return values and exceptions are to be handled through the callbacks.
10. * This method is expected to return almost immediately, after starting a {@link Thread} or similar.
11. *
12. * @return computed result
13. * @throws Exception if unable to compute a result
14. */
15. public void call(final Callback<T> pCallback, final
16. }
[java]
view plain
copy
1. public interface
2. // ===========================================================
3. // Final Fields
4. // ===========================================================
5. // ===========================================================
6. // Methods
7. // ===========================================================
8. /**
9. * 当加载完成后回调,加载完毕的事后处理
10. */
11. public void onCallback(final
12. }
[java]
view plain
copy
1. public interface
2. // ===========================================================
3. // Constants
4. // ===========================================================
5. // ===========================================================
6. // Methods
7. // ===========================================================
8. /**
9. * @param pProgress between 0 and 100.
10. */
11. public void onProgressChanged(final int
12. }
[java]
view plain
copy
1. public interface
2. // ===========================================================
3. // Constants
4. // ===========================================================
5. // ===========================================================
6. // Methods
7. // ===========================================================
8. /**
9. * @param pProgress between 0 and 100.
10. */
11. public void onProgressChanged(final int
12. }
[java]
view plain
copy
1. public class BaseActivity extends
2.
3. /**
4. *
5. * @param <T> 模板参数,操作时要返回的内容
6. * @param pCallable 需要异步调用的操作
7. * @param pCallback 回调
8. */
9. protected <T> void doAsync(final Callable<T> pCallable, final
10. this, null, "内容读取中,请稍等...", pCallable, pCallback, null, false);
11. }
12.
13. protected <T> void doAsync(final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final
14. this, pTitle, pMessage, pCallable, pCallback, null, false);
15. }
16.
17. /**
18. * Performs a task in the background, showing a {@link ProgressDialog},
19. * while the {@link Callable} is being processed.
20. *
21. * @param <T>
22. * @param pTitleResID
23. * @param pMessageResID
24. * @param pErrorMessageResID
25. * @param pCallable
26. * @param pCallback
27. */
28. protected <T> void doAsync(final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final
29. this.doAsync(pTitleResID, pMessageResID, pCallable, pCallback, null);
30. }
31. /**
32. * Performs a task in the background, showing a indeterminate {@link ProgressDialog},
33. * while the {@link Callable} is being processed.
34. *
35. * @param <T>
36. * @param pTitleResID
37. * @param pMessageResID
38. * @param pErrorMessageResID
39. * @param pCallable
40. * @param pCallback
41. * @param pExceptionCallback
42. */
43. protected <T> void doAsync(final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final
44. this, pTitleResID, pMessageResID, pCallable, pCallback, pExceptionCallback);
45. }
46. /**
47. * Performs a task in the background, showing a {@link ProgressDialog} with an ProgressBar,
48. * while the {@link AsyncCallable} is being processed.
49. *
50. * @param <T>
51. * @param pTitleResID
52. * @param pMessageResID
53. * @param pErrorMessageResID
54. * @param pAsyncCallable
55. * @param pCallback
56. */
57. protected <T> void doProgressAsync(final int pTitleResID, final ProgressCallable<T> pCallable, final
58. this.doProgressAsync(pTitleResID, pCallable, pCallback, null);
59. }
60. /**
61. * Performs a task in the background, showing a {@link ProgressDialog} with a ProgressBar,
62. * while the {@link AsyncCallable} is being processed.
63. *
64. * @param <T>
65. * @param pTitleResID
66. * @param pMessageResID
67. * @param pErrorMessageResID
68. * @param pAsyncCallable
69. * @param pCallback
70. * @param pExceptionCallback
71. */
72. protected <T> void doProgressAsync(final int pTitleResID, final ProgressCallable<T> pCallable, final Callback<T> pCallback, final
73. this, pTitleResID, pCallable, pCallback, pExceptionCallback);
74. }
75. /**
76. * Performs a task in the background, showing an indeterminate {@link ProgressDialog},
77. * while the {@link AsyncCallable} is being processed.
78. *
79. * @param <T>
80. * @param pTitleResID
81. * @param pMessageResID
82. * @param pErrorMessageResID
83. * @param pAsyncCallable
84. * @param pCallback
85. * @param pExceptionCallback
86. */
87. protected <T> void doAsync(final int pTitleResID, final int pMessageResID, final AsyncCallable<T> pAsyncCallable, final Callback<T> pCallback, final
88. this, pTitleResID, pMessageResID, pAsyncCallable, pCallback, pExceptionCallback);
89. }
90. }