当前位置:操作系统 > 安卓/Android >>

Android 异步更新UI----handler+thread

android应用是单线程模式的。
 
 
单线程模式需要记住两条:
 
一、防止UI线程阻塞
 
二、确保只在UI线程中访问Android UI工具包
 
在开发Android应用时必须遵守单线程模型的原则:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和ui相关的事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。
 
开一个线程或者在后台线程中来执行耗时的操作,如下面的例子:
 
public void onClick( View v ) {  
 
new Thread( new Runnable() {   
 
    public void run() {  
 
Bitmap b = loadImageFromNetwork();   //从网络上下载图片
 
mImageView.setImageBitmap( b );  //把图片设置给ImageView
 
}
 
    }).start()
 
 }
 
上面的代码会报错,你可能会说逻辑很正确啊,但是它违背了Android单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行.
 
例如: 如果在非UI线程直接对UI进行了操作,则会报错:
 
CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views
 
Android为我息循环们提供了消的机制,我们可以利用这个机制来实现线程间的通信。那么,我们就可以在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作。
 
Andriod提供了几种在其他线程中访问UI线程的方法:
 
 
Activity.runOnUiThread( Runnable )
 
View.post( Runnable )   
 
View.postDelayed( Runnable, long )   
 
Hanlder
 
对于运算量较大的操作和IO操作,我们需要新开线程来处理这些繁重的工作,以免阻塞ui线程。
 
例子:下面我们以获取CSDN logo的例子,演示如何使用Thread+Handler的方式实现在非UI线程发送消息通知UI线程更新界面
 
ThradHandlerActivity.java:
[java]  
<span style="font-size:18px">package com.example.thread;  
  
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 com.example.test.R;  
  
import android.annotation.SuppressLint;  
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;  
      
    @SuppressLint("HandlerLeak")  
    private Handler mHandler = new Handler(){  
        @Override  
        public void handleMessage(Message msg) {  
            switch (msg.what) {  
            case MSG_SUCCESS:  
                mImageView.setImageBitmap((Bitmap)msg.obj);  
                Toast.makeText(getApplication(), "成功获取图片", Toast.LENGTH_LONG).show();    
                break;   
  
            case MSG_FAILURE:    
                Toast.makeText(getApplication(), "获取图片失败", Toast.LENGTH_LONG).show();    
                break;  
            }  
            super.handleMessage(msg);  
        }  
          
    };  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.thread_layout);  
        mImageView= (ImageView) findViewById(R.id.logo);//显示图片的ImageView    
        mButton = (Button) findViewById(R.id.click);  
        mButton.setOnClickListener(new OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                if (mThread == null) {  
                    mThread = new Thread(runnable);  
                    mThread.start();  
                }else {    
                    Toast.makeText(getApplication(), "线程已经运行", Toast.LENGTH_LONG).show();    
                }   
            }  
        });  
    }  
      
    Runnable runnable = new Runnable() {  
        @Override  
        public void run() {  
            HttpClient hc = new DefaultHttpClient();  
            HttpGet hg = new HttpGet("http://csdnimg.cn/www/images/csdnindex_logo.gif");  
            final Bitmap bm;  
            try {  
                HttpResponse hr = hc.execute(hg);  
                bm = BitmapFactory.decodeStream(hr.getEntity().getContent());  
          &
补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,