android的異步加載與UI

原帖地址: http://blog.163.com/freemanls@126/blog/static/16458506120117702029517/

android的異步加載與UI  

2011-08-07 12:55:27|  分類: Android |  標籤:android  異步  圖片   |字號 訂閱

前言

今天我們探討的內容是andorid中的異步,同時就異步問題對UI進行聯合探討。

         本章內容希望讀者熟悉java基礎,對線程有熟悉。


        

         我們知道,java中的線程是指異步,也就是在主程序進行的同時,副程序也在進行(比喻)。Java中,實現異步一般使用2種方法,一種是實現接口Runable,一種是繼承類Thread。不過這不是我們今天要討論的內容,上面的所的東西只是你應該知道並且瞭解的東西。今天我們講述的重點是android的異步。

         Android中,異步實現,一般用handler和AsyncTask,通常handler是一個消息棧,而AsyncTask不是。

         我們今天將的是AsyncTask作爲異步的教學。你會問了,爲啥不用handler?具體的我們可以看如下解釋:

         “很多網友可能發現Android平臺很多應用使用的都是AsyncTask,而並非Thread和Handler去更新UI,這裏給大家說下他們到底有什麼區別,我們平時應該使用哪種解決方案。從Android 1.5開始系統將AsyncTask引入到android.os包中,過去在很早1.1和1.0 SDK時其實官方將其命名爲UserTask,其內部是JDK 1.5開始新增的concurrent庫,做過J2EE的網友可能明白併發庫效率和強大性,比Java原始的Thread更靈活和強大,但對於輕量級的使用更爲佔用系統資源。Thread是Java早期爲實現多線程而設計的,比較簡單不支持concurrent中很多特性在同步和線程池類中需要自己去實現很多的東西,對於分佈式應用來說更需要自己寫調度代碼,而爲了Android UI的刷新Google引入了Handler和Looper機制,它們均基於消息實現,有事可能消息隊列阻塞或其他原因無法準確的使用。

 

Android開發網推薦大家使用AsyncTask代替Thread+Handler的方式,不僅調用上更爲簡單,經過實測更可靠一些,Google在Browser中大量使用了異步任務作爲處理耗時的I/O操作,比如下載文件、讀寫數據庫等等,它們在本質上都離不開消息,但是AsyncTask相比Thread加Handler更爲可靠,更易於維護,但AsyncTask缺點也是有的比如一旦線程開啓即dobackground方法執行後無法給線程發送消息,僅能通過預先設置好的標記來控制邏輯,當然可以通過線程的掛起等待標誌位的改變來通訊,對於某些應用Thread和Handler以及Looper可能更靈活。”

        

         當然 handler+Thread方式我們還是會講解的,屆時大家也可以看到一個對比。

 

AsyncTask初識

         我在做一個圖片管理器,在圖片展示的時候,出現了很多問題,其中最重要的問題就是用戶體驗:比如九宮圖的時候,我最開始使用的是同步代碼進行圖片加載,結果30多張圖片讓我等了10秒,當然,就算算上讀出圖片進行處理的過程,這個時間我也不能接受。

         異步可以在一定程度上減輕這部分的延遲,提高用戶體驗,它的思路是:即時加載圖片,即時更新圖片列表。所以我在九宮圖的時候,可以看到圖片的一張一張刷新——這就是異步操作。

         OK。我們知道android的後臺是java寫的,我們可以用Thread跟Runalbe來實現異步,在java中,他們確實是異步,但是我們今天是要異步更換UI界面的東西。做過系統的人可能知道(我也是看別人的博客知道的),任何UI的更新必須在activity主線程中進行,因爲這樣才能保證一定的安全(這一部分我也不是非常瞭解,爲了不誤導各位,請大家看其他資料,我也會持續補充的)。

         那麼Android是怎麼解決的呢?用handler+Thread/Runable或者AsyncTask,他們是activity主線程中“僞造”的線程,並不見得分配線程ID給他們,所以能夠更新!我們今天使用AsyncTask進行異步圖片的講解,同時,對於handler的異步,我想我會用一個幻燈片的例子,來給自己和大家一個交代。

        

AsyncTask的代碼結構

         之前我們將過AsyncTask是用來做異步的。我也說過將異步的圖片即時加載到UI上去——怎麼加載?

         我們先用文字描述下AsyncTask的入參和內部的方法——我們會用到的或者說比較常用的方法。

1)         入參

我們一般用一個類來定義一個異步。比如下面這種

class AsyncTaskLoad extends AsyncTask<Object, Bitmap, Object>

我們看到了有3個入參,他們分別是

l  Params, the type of the parameters sent to the task upon execution.

l  Progress, the type of the progress units published during the background computation.

l  Result, the type of the result of the background computation.

上面是對此的解釋

l  遞交給異步處理的入參

l  在更新時候或者處理時候的入參

l  返回結果

我來解釋下第二條,我們在後臺處理過後,需要即時通知UI更新,調用的方法的入參。如果不明白,之後的代碼會詳細說明的。

2)         方法

繼承了AsyncTask,默認要實現的方法是doInBackground:

@Override

       protected Object doInBackground(Object... params)

       這貨就是後臺異步的邏輯處理,比如我們的圖片,在數據庫中抓取、處理就是在這裏寫的。同時當我們是一個循環的時候,我們會在裏面寫一段話調用更新方法,這句話是:

       // 在此提醒前臺九宮圖更新,此時原圖應該也刷出來了

       publishProgress(bitmap);

       恩,我說下,bitmap是一個Bitmap的實例化。我們調用的方法入參是Bitmap型的(跟類聲明聯繫一起,第二個入參),他會調用方法:

       @Override

       protected void onProgressUpdate(Bitmap... values) {

           // TODO Auto-generated method stub

           // super.onProgressUpdate(values);

           /* 將數據放入adapter中,並且通知頁面UI刷新 */

           for (Bitmap bitmap : values) {

              // 添加內容到adapter

              imageAdapter.addPhoto(bitmap);

              // 通知頁面UI刷新數據

              imageAdapter.notifyDataSetChanged();

           }

       }     

恩,這就是我們的更新方法。我們看到方法入參是一個Bitmap,這個定義是在類繼承的時候第二個入參定義的。入參爲Bitmap... values,這你可以理解爲

Bitmap[] values,更多資料請查略資料,這個不提了。

內容是循環values,第一個是將位圖添加到適配器adapter中,另一個notifyDataSetChanged就是一個關鍵點,他通知adapter本身數據更新了,你應該更新UI展示。

 

我們完成異步圖片加載,基本來說就只需要上面2個方法就可以做到。但是AsyncTask還有一些方法,我們需要知曉,他們分別是:

@Override

       protected void onPostExecute(Object result)

                   異步結束操作,我們看到入參是我們類繼承方法定義的Object

@Override

protected void onPreExecute() {

// TODO Auto-generated method stub

super.onPreExecute();

}

異步邏輯處理前操作(doInBackground方法執行前)。

 

onPreExecute,onPostExecute,以及onProgressUpdate都可以對UI進行操作,他們的不同處是在異步執行的先後次序不一樣。onPreExecute是先邏輯執行,onProgressUpdate是邏輯中執行,onPostExecute是異步邏輯完全執行完畢後執行。

 

 

代碼和其他說明

基本上也講完了,接下來就是貼代碼了,使用115網盤。

http://u.115.com/file/clqcacyn

代碼實現的功能是:

?  完成九宮圖的異步加載;

?  完成點擊九宮圖,顯示點擊的圖片序列號。

來一張截圖

(原創)android的異步加載與UI - 梁生 - 梁生的窩
 

需要提下的是,我的代碼是通過在sdcard中獲取圖片,如果要運行代碼,請預先配置好資源,否則啓動報錯。關於android的sd卡配置,網上有很多資料的。順便提下,如果要結合eclipse進行,請選用elipse伽利略版以上版本的。要不啓動sdcard會比較麻煩。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章