天天看點

【移動開發】Android中異步加載資料(二)AsyncTask異步更新界面

   今天介紹第二種異步更新界面的方式:AsyncTask

官方文檔:

   AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

   AsyncTask能夠更恰當和更簡單的去使用UI線程。這個類允許執行背景操作和展現結果在UI線程上,無需操縱線程和/或處理程式。AsyncTask的内部實作是一個線程池,每個背景任務會送出到線程池中的線程執行,然後使用Thread+Handler的方式調用回調函數。

1.AsyncTask抽象出背景線程運作的五個狀态:

   分别是:1、準備運作,2、正在背景運作,3、進度更新,4、完成背景任務,5、取消任務,對于這五個階段,AsyncTask提供了五個回調函數:

   1、準備運作:onPreExecute(),該回調函數在任務被執行之後立即由UI線程調用。這個步驟通常用來建立任務,在使用者接口(UI)上顯示進度條。

   2、正在背景運作:doInParams...),該回調函數由背景線程在onPreExecute()方法執行結束後立即調用。通常在這裡執行耗時的背景計算。計算的結果必須由該函數傳回,并被傳遞到onPostExecute()中。在該函數内也可以使用publishProgress(Progress...)來釋出一個或多個進度機關(unitsof progress)。這些值将會在onProgressUpdate(Progress...)中被釋出到UI線程。

   3. 進度更新:onProgressUpdate(Progress...),該函數由UI線程在publishProgress(Progress...)方法調用完後被調用。一般用于動态地顯示一個進度條。

   4. 完成背景任務:onPostExecute(Result),當背景計算結束後調用。背景計算的結果會被作為參數傳遞給這一函數。

   5、取消任務:onCancelled (),在調用AsyncTask的cancel()方法時調用

2.使用:

   AsyncTask必須使用子類。子類會覆寫至少一個方法(doInParams…)),通常将覆寫第二個(onPostExecute(結果)。< /span>

       1.Params,傳遞給背景任務的參數類型。

       2.Progress,背景計算執行過程中,進步機關(progress units)的類型。(就是背景程式已經執行了百分之幾了。)

       3.Result, 背景執行傳回的結果的類型。

  AsyncTask并不總是需要使用上面的全部3種類型。辨別不使用的類型很簡單,隻需要使用Void類型即可。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

<code>import</code> <code>java.io.InputStream;</code>

<code>import</code> <code>java.net.HttpURLConnection;</code>

<code>import</code> <code>java.net.URL;</code>

<code>import</code> <code>android.app.Activity;</code>

<code>import</code> <code>android.graphics.Bitmap;</code>

<code>import</code> <code>android.graphics.BitmapFactory;</code>

<code>import</code> <code>android.os.AsyncTask;</code>

<code>import</code> <code>android.os.Bundle;</code>

<code>import</code> <code>android.view.View;</code>

<code>import</code> <code>android.view.View.OnClickListener;</code>

<code>import</code> <code>android.widget.Button;</code>

<code>import</code> <code>android.widget.ImageView;</code>

<code>import</code> <code>android.widget.ProgressBar;</code>

<code>import</code> <code>android.widget.Toast;</code>

<code>/**</code>

<code> </code><code>* AsyncTask  實作異步加載圖檔</code>

<code> </code><code>* @author ZHF</code>

<code> </code><code>*</code>

<code> </code><code>*/</code>

<code>public</code> <code>class</code> <code>MainActivity </code><code>extends</code> <code>Activity {</code>

<code>                                                                                                                                       </code> 

<code>    </code><code>public</code> <code>static</code>  <code>final</code> <code>String IMG_URL=</code><code>"http://images.51cto.com/images/index/Images/Logo.gif"</code><code>;</code>

<code>    </code><code>Button btn_asynctask;</code>

<code>    </code><code>ImageView imgView;</code>

<code>    </code><code>ProgressBar progressBar;</code>

<code>    </code><code>@Override</code>

<code>    </code><code>protected</code> <code>void</code> <code>onCreate(Bundle savedInstanceState) {</code>

<code>        </code><code>super</code><code>.onCreate(savedInstanceState);</code>

<code>        </code><code>setContentView(R.layout.activity_main);</code>

<code>        </code><code>//加載控件</code>

<code>        </code><code>imgView = (ImageView) </code><code>this</code><code>.findViewById(R.id.imageView);</code>

<code>        </code><code>btn_asynctask = (Button) </code><code>this</code><code>.findViewById(R.id.btn_AsyncTask);</code>

<code>        </code><code>progressBar = (ProgressBar) </code><code>this</code><code>.findViewById(R.id.progressBar);</code>

<code>        </code><code>//綁定監聽器</code>

<code>        </code><code>btn_asynctask.setOnClickListener(</code><code>new</code> <code>OnClickListener() {</code>

<code>            </code><code>@Override</code>

<code>            </code><code>public</code> <code>void</code> <code>onClick(View v) {</code>

<code>                </code><code>GetImgTask getImgTask = </code><code>new</code> <code>GetImgTask();</code>

<code>                </code><code>getImgTask.execute(IMG_URL); </code><code>//執行該任務</code>

<code>            </code><code>}</code>

<code>        </code><code>});</code>

<code>    </code><code>}</code>

<code>    </code><code>/**擷取網絡圖檔任務**/</code>

<code>    </code><code>private</code> <code>class</code> <code>GetImgTask </code><code>extends</code> <code>AsyncTask&lt;String, Integer, Bitmap&gt; {</code>

<code>                                                                                                                                           </code> 

<code>        </code><code>/**在 doInParams...)之前被調用,在ui線程執行   **/</code>

<code>        </code><code>@Override</code>

<code>        </code><code>protected</code> <code>void</code> <code>onPreExecute() {</code>

<code>             </code><code>imgView.setImageBitmap(</code><code>null</code><code>);</code>

<code>             </code><code>progressBar.setProgress(</code><code>0</code><code>);    </code><code>//進度條複位</code>

<code>        </code><code>}</code>

<code>        </code><code>/**在背景線程中執行的任務**/</code>

<code>        </code><code>protected</code> <code>Bitmap doInString...  params) {</code>

<code>                                                                                                                                               </code> 

<code>            </code><code>publishProgress(</code><code>0</code><code>); </code><code>//會調用onProgressUpdate更新界面</code>

<code>            </code><code>InputStream inputStream = </code><code>null</code><code>;</code>

<code>            </code><code>Bitmap imgBitmap = </code><code>null</code><code>;</code>

<code>            </code><code>try</code> <code>{</code>

<code>                </code><code>URL url = </code><code>new</code> <code>URL(IMG_URL);</code>

<code>                </code><code>if</code><code>(url != </code><code>null</code><code>) {</code>

<code>                    </code><code>HttpURLConnection connection = (HttpURLConnection) url.openConnection();</code>

<code>                    </code><code>connection.setConnectTimeout(</code><code>2000</code><code>);</code>

<code>                    </code><code>connection.setDoInput(</code><code>true</code><code>);</code>

<code>                    </code><code>connection.setRequestMethod(</code><code>"GET"</code><code>);</code>

<code>                    </code><code>int</code> <code>code = connection.getResponseCode();</code>

<code>                    </code><code>if</code><code>(</code><code>200</code> <code>== code) {</code>

<code>                        </code><code>inputStream = connection.getInputStream();</code>

<code>                        </code><code>imgBitmap = BitmapFactory.decodeStream(inputStream);</code>

<code>                    </code><code>}</code>

<code>                </code><code>}</code>

<code>            </code><code>} </code><code>catch</code> <code>(Exception e) {</code>

<code>                </code><code>e.printStackTrace();</code>

<code>                </code><code>return</code> <code>null</code><code>;</code>

<code>            </code><code>publishProgress(</code><code>100</code><code>); </code><code>//下載下傳完成,更新進度條為滿格</code>

<code>            </code><code>//這裡不是UI線程,故不能直接setImage(imgBitmap),</code>

<code>            </code><code>return</code> <code>imgBitmap;</code>

<code>        </code><code>/**在調用publishProgress之後被調用,在ui線程執行  **/</code>

<code>        </code><code>protected</code> <code>void</code> <code>onProgressUpdate(Integer... values) {</code>

<code>            </code><code>progressBar.setProgress(values[</code><code>0</code><code>]);  </code><code>//設定進度條的進度</code>

<code>        </code><code>/**在背景線程執行完成之後,調用該方法,擷取資料更新界面**/</code>

<code>        </code><code>protected</code> <code>void</code> <code>onPostExecute(Bitmap result) {</code>

<code>            </code><code>if</code><code>(result != </code><code>null</code><code>) {</code>

<code>                </code><code>Toast.makeText(MainActivity.</code><code>this</code><code>, </code><code>"成功擷取圖檔"</code><code>, Toast.LENGTH_LONG).show();</code>

<code>                </code><code>imgView.setImageBitmap(result);</code>

<code>            </code><code>}</code><code>else</code> <code>{</code>

<code>                </code><code>Toast.makeText(MainActivity.</code><code>this</code><code>, </code><code>"擷取圖檔失敗"</code><code>, Toast.LENGTH_LONG).show();</code>

<code>        </code><code>/**取消任務,在ui線程執行 **/</code>

<code>        </code><code>protected</code> <code>void</code> <code>onCancelled() {</code>

<code>            </code><code>progressBar.setProgress(</code><code>0</code><code>);</code><code>//進度條複位</code>

<code>            </code><code>super</code><code>.onCancelled();</code>

<code>}</code>

分析:

   1.點選按鈕之後,建立一個任務,參數值為url(是以第一個參數為String)

   2.UI線程執行onPreExecute(),把ImageView的圖檔清空,progrssbar的進度清零。

   3.背景線程執行doInBackground(),不可以在doInBackground()操作ui,調用publishProgress(0)更新進度,此時會調用onProgressUpdate(Integer...progress)更新進度條(進度用整形表示,是以AsyncTask的第二個模闆參數是Integer)。函數最後傳回result(例子中是傳回Bitmap類型,是以AsyncTask的第三個模闆參數是Bitmap)。

   4.當背景任務執行完成後,調用onPostExecute(Result),傳入的參數是doInBackground()中傳回的對象。

參考部落格:http://blog.csdn.net/mylzc/article/details/6772129

  源碼下載下傳請看附件

<a href="http://down.51cto.com/data/2363166" target="_blank">附件:http://down.51cto.com/data/2363166</a>

     本文轉自zhf651555765 51CTO部落格,原文連結:http://blog.51cto.com/smallwoniu/1252156,如需轉載請自行聯系原作者