生活随笔
收集整理的這篇文章主要介紹了
Android多线程分析之一:使用Thread异步下载图像
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
打算整理一下對 Android Framework 中多線程相關知識的理解,主要集中在 Framework 層的 Thread, Handler, Looper, MessageQueue, Message, AysncTask,當然不可避免地要涉及到 native 方法,因此也會分析 dalvik 中和線程以及消息處理相關的代碼:如 dalvik 中的 C++ Thread 類以及 MessageQueue 類。本文將從一個使用 Thread 的簡單 應用入手,引入 Thread 這個話題,接下來的幾篇文章會依次介紹前面提到的那些主題。
這是一個使用 Android Thread 從網絡上異步下載圖片并在 ImageView 中顯示的的簡單示例。因為需要訪問網絡,所以要在 manifest.xml 中添加網絡訪問權限:
[html]?view plaincopy print?
<uses-permission?android:name="android.permission.INTERNET">?? </uses-permission>??
布局文件很簡單,一個 Button,一個 ImageView:
[html]?view plaincopy print?
<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"?? ????xmlns:tools="http://schemas.android.com/tools"?? ????android:layout_width="match_parent"?? ????android:layout_height="match_parent"?? ????android:orientation="vertical"?? ????android:padding="10dip"?>?? ?? ????<Button?? ????????android:id="@+id/LoadButton"?? ????????android:layout_width="fill_parent"?? ????????android:layout_height="wrap_content"?? ????????android:text="Load">?? ????</Button>?? ?? ????<ImageView?? ????????android:id="@+id/ImageVivew"??? ????????android:layout_width="match_parent"??? ????????android:layout_height="400dip"??? ????????android:scaleType="centerInside"??? ????????android:padding="2dp">?? ????</ImageView>??? ?????? </LinearLayout>??
接下來看代碼:
首先來看定義:圖片的 url 路徑,兩個消息值以及一些控件:
[java]?view plaincopy print?
???private?static?final?String?sImageUrl?=?"http://fashion.qqread.com/ArtImage/20110225/0083_13.jpg";?? ?? private?static?final?int?MSG_LOAD_SUCCESS?=?0;?? private?static?final?int?MSG_LOAD_FAILURE?=?1;?? ?? ???private?Button?mLoadButton;?? ???private?ProgressDialog?mProgressBar;?? ???private?ImageView?mImageView;??
然后來看控件的設置:
[java]?view plaincopy print?
protected?void?onCreate(Bundle?savedInstanceState)?{?? ????super.onCreate(savedInstanceState);?? ????setContentView(R.layout.activity_main);?? ?????? ????Log.i("UI?thread",?"?>>?onCreate()");?? ?????? ????mProgressBar?=?new?ProgressDialog(this);?? ????mProgressBar.setCancelable(true);?? ????mProgressBar.setMessage("Image?downloading?...");?? ????mProgressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);?? ????mProgressBar.setMax(100);?? ?????? ????mImageView?=?(ImageView)this.findViewById(R.id.ImageVivew);?? ?????? ????mLoadButton?=?(Button)this.findViewById(R.id.LoadButton);?? ????mLoadButton.setOnClickListener(new?View.OnClickListener()?{?? ???????????@Override??? ???????????public?void?onClick(View?v)?{?? ????????????mProgressBar.setProgress(0);?? ????????????mProgressBar.show();?? ?????????????? ????????????<strong>new?Thread()?{</strong>?? ????????????????@Override?? ????????????????<strong>public?void?run()?{</strong>?? ????????????????????Log.i("Load?thread",?"?>>?run()");?? ???????????????????????Bitmap?bitmap?=?loadImageFromUrl(sImageUrl);?? ???????????????????????if?(bitmap?!=?null)?{?? ????????????????????<strong>????Message?msg?=?mHandler.obtainMessage(MSG_LOAD_SUCCESS,?bitmap);?? ????????????????????????mHandler.sendMessage(msg);</strong>?? ???????????????????????}?? ???????????????????????else?{?? ????????????<strong>????????????Message?msg?=?mHandler.obtainMessage(MSG_LOAD_FAILURE,?null);?? ????????????????????????mHandler.sendMessage(msg);</strong>?? ???????????????????????}?? ????????????????}?? ????????????}.start();?? ???????????}?? ???????});?? }??
loadImageFromUrl 是一個從網絡下載 Bitmap 的 static 函數:
[java]?view plaincopy print?
static?Bitmap?loadImageFromUrl(String?uil)?{?? ????Bitmap?bitmap?=?null;?? ????try{?? ????????InputStream?in?=?new?java.net.URL(sImageUrl).openStream();?? ????????bitmap?=?BitmapFactory.decodeStream(in);?? ????????in.close();?? ????}?? ????catch?(Exception?e)?{?? ????????e.printStackTrace();?? ????}?? ????return?bitmap;?? }??
mHandler 是主線程也就是 UI 線程處理消息的 Handler:
[java]?view plaincopy print?
private?<strong>Handler?mHandler=?new?Handler()</strong>{?? ????@Override?? ????public?void?<strong>handleMessage</strong>(Message?msg)?{?? ????????Log.i("UI?thread",?"?>>?handleMessage()");?? ?????????? ????????switch(msg.what){?? ????????case?MSG_LOAD_SUCCESS:?? ????????????Bitmap?bitmap?=?(Bitmap)?msg.obj;?? ????????????mImageView.setImageBitmap(bitmap);?? ?????????????? ????????????mProgressBar.setProgress(100);?? ????????????mProgressBar.setMessage("Image?downloading?success!");?? ????????????mProgressBar.dismiss();?? ????????????break;?? ?????????????? ????????case?MSG_LOAD_FAILURE:?? ????????????mProgressBar.setMessage("Image?downloading?failure!");?? ????????????mProgressBar.dismiss();?? ????????????break;?? ????????}?? ????}?? };??
縱觀上面的代碼,當點擊 load 按鈕時,會創建一個匿名 Thread,并調用其 start() 啟動運行線程,在這個線程中進行圖像下載并解碼成 Bitmap,然后通過 Handler 向 UI 線程發送消息以通知下載結果。這都是在匿名 Thead 中處理的。主線程也就是 UI 線程收到消息之后,會分發給 Handler,在它的 handleMessage 方法中根據消息 id 來處理下載結果,要么成功要么失敗,并相應地更新 UI。
運行該示例:
可以從 logcat 的第四欄看到 UI thread(tid: 817) 和 Load thread(tid: 830) 的線 程id 是不同的,因為它們是兩個獨立的線程。
在匿名線程下載完畢之后,為什么不直接在這個線程的 run() 中更新 UI 呢?這樣做有什么后果?這些問題將在后文詳細解答。
總結
以上是生活随笔為你收集整理的Android多线程分析之一:使用Thread异步下载图像的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。