Android开发 - Handler的使用

back >>

1. Handler的作用

    * handler 主要用于消息的异步处理(处理一个耗时较长并且可能不一定有结果的操作)
        - 我的理解,handler就是一个消息队列的这样的数据结构
        - 它提供了一个线程异步处理的方案,可将本线程(当前Activity线程,即HandlerActivity线程)和post到handler里的线程异步执行(也就是并行操作,互不干扰)
        - 可以往handler里添加线程对象,也可以删除线程对象。队列的操作方式是先进先出
        - 线程对象从消息队列中取出后,就会执行该线程对象的run方法,从而执行指定的操作

 

    * handler例子--控制进度条(工程代码请参考01_14_src.zip)

        - handler 里其实有两个队列,一个是线程队列,一个是消息队列

package mars.barhandler;

import android.app.Activity;
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.ProgressBar;
/**
 * 执行流程
 * 1.点击startButton按钮,执行class ButtonListener中的onClick方法
 * 2.onClick方法设置进度条可见,handler将updateThread线程对象添加到线程队列中
 * 3.updateThread压入到线程队列中后,线程队列中就只有该线程对象,就会立即执行
 * 4.updateThread线程对象的run方法运行
 * 5.updateBarHandler.sendMessage(msg)执行,是将消息压入到消息队列中
 * 6.消息队列中有消息,updateBarHandler对象的handleMessage方法会执行,从消息队列中取消息,并将线程对象再次压入到线程队列中
 * 
 * 由此可见handler中至少有两个队列,一个是线程队列,一个是消息队列
 */
public class TestBarHandler extends Activity {
    /** Called when the activity is first created. */
	//声明控件变量
	ProgressBar bar = null;
	Button startButton = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //根据控件的ID得到代表控件的对象,并为按钮设置监听器
        bar = (ProgressBar)findViewById(R.id.bar);
        startButton = (Button)findViewById(R.id.startButton);
        startButton.setOnClickListener(new ButtonListener());// 监听器
    }
    //当点击startButton按钮时,就会执行ButtonListener的onClick方法
    class ButtonListener implements OnClickListener{

		@Override
		public void onClick(View v) {
			// 设置进度条处于可见状态
			bar.setVisibility(View.VISIBLE);
			updateBarHandler.post(updateThread);//将线程压入到线程队列中
		}
    	
    }
    //使用匿名内部类来复写Handler当中的handleMessage方法
    Handler updateBarHandler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			bar.setProgress(msg.arg1);
			Bundle bundle = msg.getData();
			updateBarHandler.post(updateThread);//将线程压入到线程队列中
			System.out.println("test---->" + bundle.getString("test"));
		}
    	
    };
    //线程类,该类使用匿名内部类的方式进行声明
    Runnable updateThread = new Runnable(){
    	int i = 0 ;
		@Override
		public void run() {
			System.out.println("Begin Thread" + i);
			i = i + 10 ;
			//得到一个消息对象,Message类是有Android操作系统提供
			Message msg = updateBarHandler.obtainMessage();
			
			//将msg对象的arg1参数的值设置为i,用arg1和arg2这两个成员变量传递消息,优点是系统性能消耗较少
			msg.arg1 = i ;
			Bundle bundle = new Bundle();
			bundle.putString("test", "test bundle");
			msg.setData(bundle);
			try {
				//设置当前显示睡眠1秒
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//将msg对象加入到消息队列当中
			if( i > 100){
				//如果当i的值为100时,就将线程对象从handler当中移除
				updateBarHandler.removeCallbacks(updateThread);
				System.out.println(">>>>>>");
			}else{
				updateBarHandler.sendMessage(msg);//send后就会在handleMessage方法中获得该msg
				System.out.println("<<<<<<");
			}
		}
    };
    class MyThread extends Thread{
    	public void run(){
    		
    	}
    }
    
} 


2. Handler与线程的关系
    * 默认情况下,handler和调用该handler的activity是同一个线程(工程代码见01_15_src.zip)
        - 因为handler处理post到线程队列中的线程对象时,其实是直接执行了该线程对象的run方法,而不是start方法
    要想真正开辟一个新线程,需要如下操作:

        HandlerThread handlerThread = new HandlerThread("handler_thread");
        handlerThread.start();
        //然后覆写Handler类的方法
        class MyHandler extends Handler {
            public MyHandler() {
   
            }
   
            public MyHandler(Looper looper) {
                super(looper);
            }
   
            public void handleMessage(Message msg) {
                //接收数据
                Bundle b=msg.getData();
                int age =b.getInt("age");
                System.out.println("age:"+age);
                System.out.println(Thread.currentThread().getId());
                System.out.println("handlerMessage");
            }
        }
        MyHandler myHandler = new MyHandler(handlerThread.getLooper());
        Message msg = myHandler.obtainMessage();//获得消息
        Bundle b=new Bundle();
        b.putInt("age", 20);
        msg.setData(b);
        msg.sendToTarget();//发送消息
       
        发送消息的两种方法:
        --myHandler.sendMessage(msg);
        --msg.sendToTarget();


3. bundle对象
    * bundle对象其实就是一个数据存储的工具,一般用于向消息传递数据
        - 同hashmap有点像,只是bundle键值对的键是String的,而值可以随便。
    * 向消息传递数据的方式:
        - 使用Message的成员变量
            msg.arg1,msg.arg2,msg.obj等
        - 使用bundle
            Bundle b=new Bundle();
            b.putInt("age", 20);
            msg.setData(b);
   
4. Looper对象
    * 循环从队列中取得消息
        - 一般自己不创建。android提供了HandlerThread类实现循环从队列中取消息的功能,handlerThread.getLooper()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值