Android非同步機制一:使用Thread+Handler實現非UI線程更新UI介面

來源:互聯網
上載者:User

標籤:thread   handler   非ui線程   更新ui介面   

概述:每個Android應用程式都運行在一個dalvik虛擬機器進程中,進程開始的時候會啟動一個主線程(MainThread),主線程負責處理和ui相關的事件,因此主線程通常又叫UI線程。而由於Android採用UI單執行緒模式,所以只能在主線程中對UI元素進行操作。如果在非UI線程直接對UI進行了操作,則會報錯:

CalledFromWrongThreadException only the original thread that created a view hierarchy can touch its views

Android為我們提供了訊息迴圈的機制,我們可以利用這個機制來實現線程間的通訊。那麼,我們就可以在非UI線程發送訊息到UI線程,最終讓Ui線程來進行ui的操作。

對於運算量較大的操作和IO操作,我們需要新開線程來處理這些繁重的工作,以免阻塞ui線程。

例子:下面我們以擷取CSDN logo的例子,示範如何使用Thread+Handler的方式實現在非UI線程發送訊息通知UI線程更新介面。

ThradHandlerActivity.java:

package com.lc.androidasyntask;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;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;public class ThreadHandlerActivity extends Activity {    private static final int MSG_SUCCESS = 0;// 擷取圖片成功的標識    private static final int MSG_FAILURE = 1;// 擷取圖片失敗的標識    private ImageView mImageView;    private Button mButton;    private Thread mThread;    private Handler mHandler = new Handler() {        public void handleMessage(Message msg) {// 此方法在ui線程運行            switch (msg.what) {            case MSG_SUCCESS:                mImageView.setImageBitmap((Bitmap) msg.obj);// imageview顯示從網路擷取到的logo                Toast.makeText(getApplication(),                        getApplication().getString(R.string.get_pic_success),                        Toast.LENGTH_LONG).show();                break;            case MSG_FAILURE:                Toast.makeText(getApplication(),                        getApplication().getString(R.string.get_pic_failure),                        Toast.LENGTH_LONG).show();                break;            }        }    };    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        mImageView = (ImageView) findViewById(R.id.imageView);// 顯示圖片的ImageView        mButton = (Button) findViewById(R.id.button);        mButton.setOnClickListener(new OnClickListener() {            public void onClick(View v) {                if (mThread == null) {                    mThread = new Thread(runnable);                    mThread.start();// 線程啟動                } else {                    Toast.makeText(                            getApplication(),                            getApplication().getString(R.string.thread_started),                            Toast.LENGTH_LONG).show();                }            }        });    }    Runnable runnable = new Runnable() {        public void run() {// run()在新的線程中運行            HttpClient httpClient = new DefaultHttpClient();            HttpGet httpGet = new HttpGet(                    "http://csdnimg.cn/www/images/csdnindex_logo.gif");// 擷取csdn的logo            final Bitmap bitmap;            try {                HttpResponse httpResponse = httpClient.execute(httpGet);                bitmap = BitmapFactory.decodeStream(httpResponse.getEntity().getContent());            } catch (Exception e) {                mHandler.obtainMessage(MSG_FAILURE).sendToTarget();// 擷取圖片失敗                return;            }            // 擷取圖片成功,向ui線程發送MSG_SUCCESS標識和bitmap對象            mHandler.obtainMessage(MSG_SUCCESS, bitmap).sendToTarget();            // mImageView.setImageBitmap(bm); //出錯!不能在非ui線程操作ui元素            // mImageView.post(new Runnable() {//另外一種更簡潔的發送訊息給ui線程的方法。            //            // @Override            // public void run() {//run()方法會在ui線程執行            // mImageView.setImageBitmap(bm);            // }            // });        }    };}

main.xml檔案:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="擷取圖片" >    </Button>    <ImageView        android:id="@+id/imageView"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout>

strings.xml檔案:

    <string name="thread_started">Thread started</string>    <string name="get_pic_success">Get pic success</string>    <string name="get_pic_failure">Get pic failure</string>

在資訊清單檔中加入訪問網路許可權:

<!-- 不要忘記設定網路存取權限 -->    <uses-permission android:name="android.permission.INTERNET" />

然後將”com.lc.androidasyntask.ThreadHandlerActivity” 設定為啟動頁面

結果如下:

案例中我們使用Handler和Thread,線上程執行的結構中通知handler,在handler中進行 圖片的設定。

Android非同步機制一:使用Thread+Handler實現非UI線程更新UI介面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.