異步消息處理機(jī)制

異步消息處理機(jī)制

主線程又被稱(chēng)為UI線程,Android是不允許在子線程中進(jìn)行UI操作的。在主線程中進(jìn)行耗時(shí)操作,程序易發(fā)生ANR錯(cuò)誤(Application Not Response)。我們必須在子線程中執(zhí)行一些耗時(shí)操作,然后根據(jù)任務(wù)的執(zhí)行結(jié)果來(lái)更新相應(yīng)的UI控件,這就用到了異步消息處理機(jī)制。

代碼實(shí)現(xiàn):

public class MainActivity extends Activity {
    
    private static final int IMAGE = 0;

    private static final int TOAST = 1;

    static ImageView iv ;
    
    static MainActivity ma;
    
    //Handler對(duì)象設(shè)置成static,內(nèi)部變量都需要是靜態(tài)static
    static Handler handler = new Handler(){
         //此方法在主線程中調(diào)用,可以用來(lái)刷新UI
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
                case IMAGE:
                    //把位圖對(duì)象顯示至ImageView
                    iv.setImageBitmap((Bitmap) msg.obj); 
                    break;
                case TOAST:
                    Toast.makeText(ma, "請(qǐng)求失敗", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
                }
         }
     }; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);
        ma = this;
    }

    /**
     * 下載圖片
     */
    public void click(View v){
        //創(chuàng)建一個(gè)子線程,在子線程中處理網(wǎng)絡(luò)請(qǐng)求
        new Thread(){

            @Override
            public void run() {
                
                //確定網(wǎng)址
                String path = "http://192.168.1.100:8080/home_gradient.jpg";
                try {
                    //將網(wǎng)址封裝成一個(gè)Url對(duì)象
                    URL url = new URL(path);
                    //獲取客戶(hù)端和服務(wù)器的連接對(duì)象,此時(shí)還沒(méi)有建立連接
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    //對(duì)連接對(duì)象進(jìn)行初始化
                    connection.setRequestMethod("GET"); //設(shè)置請(qǐng)求方法
                    connection.setConnectTimeout(5000); //設(shè)置連接超時(shí)
                    //發(fā)送請(qǐng)求,與服務(wù)器建立連接
                    connection.connect();
                    if (connection.getResponseCode() == 200) { //如果響應(yīng)嗎為200,說(shuō)明請(qǐng)求成功
                        //獲取服務(wù)器中響應(yīng)頭中的流,流里的數(shù)據(jù)就是客戶(hù)端請(qǐng)求的數(shù)據(jù)
                        InputStream is = connection.getInputStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(is);
                        //使用Handler對(duì)象的obtainMessage方法獲取一個(gè)消息對(duì)象Message
                        Message message = handler.obtainMessage();
                        //消息對(duì)象可以攜帶數(shù)據(jù)
                        message.obj = bitmap;
                        message.what = IMAGE;
                        //把消息發(fā)送至主線程的消息隊(duì)列
                        handler.sendMessage(message);
                    }
                    else {
                        //彈出吐司也是一種UI的刷新,需要在主線程中運(yùn)行
                        Message message = handler.obtainMessage();
                        message.what = TOAST;
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    if(connection != null){
                        //關(guān)閉HTTP連接
                        connection.disconnect();
                    }
                 }
                
            }
            
        }.start(); //開(kāi)啟線程任務(wù)
        
    }
    
}

解析異步消息處理機(jī)制

異步消息處理主要由四部分組成:MessageHandlerMessageQueueLooper

  • **Message: ** Message對(duì)象是在線程之間傳遞的消息,它可以在內(nèi)部攜帶少量的信息,用于在不同的線程之間交換數(shù)據(jù)。whatarg1arg2字段攜帶一些整型數(shù)據(jù),obj字段攜帶一個(gè)object對(duì)象

  • Handler: Handler對(duì)象主要用于發(fā)送和處理消息。發(fā)送消息一般是使用sendMessage()方法,消息被發(fā)送到消息隊(duì)列(MessageQueue)中,輪詢(xún)器(Looper)會(huì)把消息對(duì)象傳遞給消息處理器(Handler),消息處理器調(diào)用handleMessage()方法,此方法運(yùn)行在主線程中,可以刷新UI

  • MessageQueue: MessageQueue對(duì)象是消息隊(duì)列的意思,主要存放所有通過(guò)Handler發(fā)送的消息。這部分消息會(huì)一直存放在消息隊(duì)列里,直至被輪詢(xún)器取出傳遞給消息處理器。每個(gè)線程中只會(huì)有一個(gè)消息隊(duì)列對(duì)象

  • Looper: Looper是輪詢(xún)器的意思,是每個(gè)線程中的消息隊(duì)列MessageQueue的管家,其會(huì)不停的檢測(cè)消息隊(duì)列中是否有消息對(duì)象,若有將從消息隊(duì)列中取出消息對(duì)象傳遞給消息處理器

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容