您好,登錄后才能下訂單哦!
在我們開發當中很多時候都會遇到:從網絡上獲取數據的操作或大量的IO數據操作時,會耗費很長時間,為了使用戶的體驗效果更好,現在大多數開發者都會使用異步的方式去處理這些的操作,異步的方式有好多種,在此我匯總了以下兩種:
1.Handler + Thread的方式
2.AsyncTask異步更新UI界面
這兩種方式各自有各自的優缺點,這里先介紹一下第一種方式
1.Hanlder介紹:
官方文檔:
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
一個處理程序允許你發送和處理消息或者Runnable對象關聯到的一個線程的MessageQueue。每個處理程序的實例相關聯著一個單個線程和一個線程的消息隊列。當你創建一個新的處理程序,它被綁定到線程/消息隊列的線程時創建它——從那時起,它將提供消息和runnables給消息隊列和執行他們出來的消息隊列。
Handler主要方法:
常用方法 | 解釋 |
Message obtainMessage(int what, Object obj) | 獲取一個Message對象,包含了一個標識和value |
boolean post(Runnable r) | 將Runnable r添加到消息隊列,之后會被UI線程執行 |
boolean postDelayed(Runnable r, long delayMillis) | 延遲多少毫秒之后,再將該線程加入到消息隊列中 |
boolean sendEmptyMessage(int what) | 發送一個只有標識的消息 |
boolean sendMessage(Message msg) | 添加一條消息到消息隊列的末尾 |
void handleMessage(Message msg) | 用于處理接收到的消息 |
簡單的說Android采用UI單線程模型,所以只能在主線程中對UI元素進行操作。如果在非UI線程直接對UI進行了操作,就會報錯,當然為了提高效率,Android為我們提供了消息循環的機制,我們可以利用這個機制來實現線程間的通信,在非UI線程發送消息到UI線程,最終讓Ui線程來進行ui的操作
2.在非UI線程中發送消息通知UI線程更新界面:
import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; /** * Handler + Thread 實現異步加載圖片 * @author ZHF * */ public class MainActivity extends Activity { private static final int MSG_SUCCESS = 0;//成功獲取圖片 private static final int MSG_FAILURE = 1;//獲取圖片失敗 public static final String IMG_URL = "http://p_w_picpaths.51cto.com/p_w_picpaths/index/Images/Logo.gi"; Button btn_handler; ImageView p_w_picpathView; private DownloadImgThread downloadImgThread; private Handler mHandler = new Handler(){ public void handleMessage(Message msg) { //該方法是在UI主線程中執行 switch(msg.what) { case MSG_SUCCESS: p_w_picpathView.setImageBitmap((Bitmap)msg.obj); //顯示圖片 break; case MSG_FAILURE: Toast.makeText(MainActivity.this, "獲取圖片失敗", Toast.LENGTH_LONG); break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); p_w_picpathView = (ImageView) this.findViewById(R.id.p_w_picpathView); btn_handler = (Button) this.findViewById(R.id.btn_handler); btn_handler.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //開啟一個非UI線程,用于下載圖片 downloadImgThread = new DownloadImgThread(); downloadImgThread.start(); } }); } /**圖片下載線程**/ private class DownloadImgThread extends Thread{ HttpURLConnection conn; InputStream inputStream; Bitmap imgBitmap; @Override public void run() { try { URL url = new URL(IMG_URL); if(url != null) { HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(2000); connection.setDoInput(true); connection.setRequestMethod("GET"); int code = connection.getResponseCode(); if(200 == code) { inputStream = connection.getInputStream(); imgBitmap = BitmapFactory.decodeStream(inputStream); //獲取圖片成功,向ui線程發送MSG_SUCCESS標識和bitmap對象 mHandler.obtainMessage(MSG_SUCCESS,imgBitmap).sendToTarget(); }else { //獲取圖片失敗,向ui線程發送MSG_FAILURE mHandler.obtainMessage(MSG_FAILURE).sendToTarget(); } } } catch (Exception e) { e.printStackTrace(); } } } }
在自己的線程中獲取到imgBitmap,不能直接p_w_picpathView.setImageBitmap(imgBitmap),會報錯的哦! 通過Message中obj將其存儲起來,傳遞到UI線程中再對其操作。
權限:
<uses-permission android:name="android.permission.INTERNET"/>
2.View的post(Runnable r)方法
在獲取到imgBitmap之后,可以通過下面代碼實現UI界面的更新哦:
//另外一種更簡潔的發送消息給ui線程的方法。 mImageView.post(new Runnable() { @Override public void run() {//run()方法會在ui線程執行 mImageView.setImageBitmap(bm); } });
這是為什么那?
因為Android框架為每個應用的主線程創建了一個隱式的handler,使用post方法的原理就是給這個隱式的handler發送一個Runnable對象,然后隱式的handler會在ui線程執行Runnable對象的run()方法。
下一篇(AsyncTask):http://smallwoniu.blog.51cto.com/3911954/1252156
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。