Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 消息機制應用

Android 消息機制應用

編輯:關於Android編程

通過一個例子來熟悉下 Android 消息機制的使用,這個例子中主線程中有一個EditText、ImageView 和一個 Button,在 EditText 中輸入圖片地址後,點擊 Button,主線程向後台線程發送消息請求下載圖片,後台線程下載完圖片後向主線程發送消息請求更新UI以顯示下載的圖片。通過這個例子一方面熟悉消息機制過的使用,另一方面理解 Handler 的雙向傳遞。最終的效果如下:

這裡寫圖片描述

主線程向後台線程發消息

這裡寫圖片描述

後台線程向主線程發消息

這裡寫圖片描述

示例源代碼

布局文件 res/layout/activity_main.xml



    
    

MainActivity 用於顯示界面,作為主線程,它接收和處理更新界面的消息。

package com.wuhui.testhandler;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

/**
 * Created by Administrator on 2015/5/6.
 */
public class MainActivity extends Activity {
    private EditText mEditText;
    private Button mButton;
    private ImageView mImageView;
    private Downloader mDownloader;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mEditText = (EditText)findViewById(R.id.edittext_url);
        mImageView = (ImageView)findViewById(R.id.imageview_image);

        /* 創建一個與主線程關聯的 Handler,並傳作為構造函數參數遞給 Downloader 對象 */
        mDownloader = new Downloader(new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case Downloader.MESSAGE_DOWNLOAD:
                        if (msg.obj != null) {
                            Bitmap bitmap = (Bitmap) msg.obj;
                            // 更新圖片
                            mImageView.setImageBitmap(bitmap);
                        }
                        break;
                    default:
                        break;
                }
            }
        });
        mDownloader.start();        // 啟動後台線程
        mDownloader.getLooper();    // 確保後台線程中的消息循環初始化

        mButton = (Button)findViewById(R.id.button_download);
        mButton.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void onClick(View v) {
                // 下載圖片
                mDownloader.downloadImage(mEditText.getText().toString());
            }
        });

    }
}

Downloader 類是一個後台線程,其繼承自 HandlerThread 類,所以它具有消息循環。Downloader類負責接收和處理下載圖片的消息。

package com.wuhui.testhandler;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by Administrator on 2015/5/6.
 */
public class Downloader extends HandlerThread{
    private static final String mName = "Downloader";
    public static final int MESSAGE_DOWNLOAD = 1;
    private Handler mHandler;               // 當前線程的 Handler
    private Handler mResponseHandler;       // 主線程的 Handler

    Downloader (Handler handler) {
        super(mName);
        mResponseHandler = handler;         // 保存主線程的 Handler
    }

    // 該函數在消息循環開始前被調用
    @Override
    protected void onLooperPrepared() {    
        super.onLooperPrepared();
        // 創建當前線程的 Handler
        mHandler = new Handler() {        
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                String imageUrl = (String)msg.obj;
                // 下載圖片
                handleDownloadImage(imageUrl);
            }
        };
    }

    public void downloadImage(String imageUrl) {
        /**
         * 這裡沒有直接調用 handleDownloadImage 來下載圖片,而是發送消息,
         * 這樣做的好處是,如果連續有多張圖片要下載,該方法也可以立即返回,
         * 由後台線程根據消息隊列中的請求依次下載圖片。
         * */

        // 將下載圖片的消息發送給當前線程的消息隊列
        mHandler.obtainMessage(MESSAGE_DOWNLOAD, imageUrl)
                .sendToTarget();
    }

    private void handleDownloadImage(String imageUrl) {
        try {
            URL url =  new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection)url.openConnection();
            connection.connect();
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return;
            }
            InputStream in = connection.getInputStream();
            byte[] buffer = new byte[512];
            int readSize = 0;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            while ((readSize = in.read(buffer)) > 0) {
                out.write(buffer, 0, readSize);
            }
            out.close();
            byte[] bitmapBytes= out.toByteArray();

            // 從下載的字節數據中解碼出圖片
            Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);

            // 向主線程發送消息,將下載的圖片作為消息參數
            mResponseHandler.obtainMessage(MESSAGE_DOWNLOAD, bitmap)
                            .sendToTarget();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上面就是全部代碼了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved