Android 多线程操作之 Handler 与 HandlerThread

1.  Handler操作 微笑

 

Handler主要用于执行消息队列的传送与runnable线程;消息队列用于多线程。注:Handler操作实际与UI主线程是一个线程,虽然主要操作在Runnable中,但是其实它与UI主线程是一个线程。

1)   创建一个Handler对象:Handler handler = new Handler();

2)   调用Handler对象的post方法,将要执行的对象添加到队列中:handler.post(runnable线程);

3)   将要执行的操作写在线程对象run方法中:

privateRunnable runnable = new Runnable(){

              public void run(){

                     //相关业务操作

}

}

4)   若要循环执行操作,可在run()方法中执行handler对象的postDelayed方法。

 

 

代码演示:

 

package com.example.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
/**
 * Handler的演示操作,演示Handler的运行机制
 * */
public class HandlerActivity extends Activity {

	//进度条
	private ProgressBar pb_handler = null;
	//开始按钮
	private Button btn_start = null;
	//结束按钮
	private Button btn_end = null;
	
	private final static String TAG = "TEST";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		pb_handler = (ProgressBar)findViewById(R.id.pb_handler);
		btn_start = (Button)findViewById(R.id.btn_start);
		Log.i(TAG, "UI主线程ID为 "+Thread.currentThread().getId());
		btn_start.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//将要执行的Runnable对象添加到消息队列中
				handler.post(runtestHandler);
			}
		});
		btn_end = (Button)findViewById(R.id.btn_end);
		btn_end.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//将正在执行的Runnable对象从消息队列移除
				handler.removeCallbacks(runtestHandler);
			}
		});
		
	}
	private int i = 0;
	private Handler handler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			//接收Runnable操作中发过来的消息信息,改变进度条的长度
			pb_handler.setProgress(msg.arg1);
		}
	};
	private Runnable runtestHandler = new Runnable() {
		
		@Override
		public void run() {
			i += 5;
			Log.i(TAG, "Handler所在线程ID为 "+Thread.currentThread().getId());
			Log.i(TAG, "数字="+i);
			//得到一个消息
			Message msg = handler.obtainMessage();
			//给消息赋值,arg1与arg2主要是一些简单的int数据,优点是消耗的资源少
			msg.arg1 = i;
			//发送消息,自动将消息赋值给Handler对象对应的HandlerMessage中Message对象
			handler.sendMessage(msg);
			handler.postDelayed(runtestHandler, 1000);
		}
	};
}

 

2.   HandlerThread操作        微笑

          Handler类既然不是新开了一个线程,必然一些操作如大数据或网络下载操作之类的就不能仅仅用Handler,针对这种情况,出现了HandlerThread类,该类用于方便的创建一个含有looper的线程类,通过此类实现多线程操作。注意:looper用来创建handler类。并且必须调用start()方法。

        将上面的demo修改为HandlerThread 多线程,演示Demo如下:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
/**
 * HandlerThread的演示操作
 * 演示HandlerThread与Handler配合使用,实现多线程的运行机制
 * 同时包含Message各种消息形式的演示
 * */
public class HandlerThreadActivity extends Activity {

	//进度条
	private ProgressBar pb_handler = null;
	//开始按钮
	private Button btn_start = null;
	//结束按钮
	private Button btn_end = null;
	
	private final static String TAG = "TEST";
	
	private HandlerThread handlerThead = null;
	private ProgressBarHandler handler = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		pb_handler = (ProgressBar)findViewById(R.id.pb_handler);
		btn_start = (Button)findViewById(R.id.btn_start);
		Log.i(TAG, "UI主线程ID为 "+Thread.currentThread().getId());
		//new一个handlerThead对象
		handlerThead = new HandlerThread("handlerThead");
		//必须调用
		handlerThead.start();
		
		
		btn_start.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				
				handler = new ProgressBarHandler(handlerThead.getLooper());
				//将要执行的Runnable对象添加到消息队列中
				handler.post(runtestHandler);
				
			}
		});
		btn_end = (Button)findViewById(R.id.btn_end);
		btn_end.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//将正在执行的Runnable对象从消息队列移除
				handler.removeCallbacks(runtestHandler);
			}
		});
		
		
	}
	private int i = 0;
	
	/**
	 * 内部类,用于Looper与Handler配合实现多线程操作,Looper轮训机制
	 * */
	class ProgressBarHandler extends Handler{
		
		public ProgressBarHandler(){
			
		}
		
		public ProgressBarHandler(Looper looper){
			super(looper);
		}
		
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			//接收Runnable操作中发过来的消息信息,改变进度条的长度
			pb_handler.setProgress(msg.arg1);
			//接收推送过来的消息中的Bundle信息
			Bundle bundle = msg.getData();
			Log.i(TAG, "Message通过Bundle传过来的内容:"+bundle.getString("str0"));
			Log.i(TAG, "Message通过Bundle传过来的内容:"+bundle.getString("str1"));
			switch(msg.what){//接收自定义的消息值
				case R.id.btn_end:{//此处仅是测试,下面这段代码会让进度条停止,进度条只前进一次
					handler.removeCallbacks(runtestHandler);
					Log.i(TAG, "此处是接收自定义消息信息");
				}
			}
		}
	};
	private Runnable runtestHandler = new Runnable() {
		

		@Override
		public void run() {
			i += 5;
			Log.i(TAG, "采用HandlerThread后Handler所在线程ID为 "+Thread.currentThread().getId());
			Log.i(TAG, "数字="+i);
			//得到一个消息
			Message msg = handler.obtainMessage();
			//给消息赋值,arg1与arg2主要是一些简单的int数据,优点是消耗的资源少
			msg.arg1 = i;
			//创建一个Bundle对象
			Bundle bundle = new Bundle();
			bundle.putString("str0", "data 1");
			bundle.putString("str1", "data 2");
			msg.setData(bundle);
			//msg.what自定义的消息值,这个东东在开发中经常使用
			msg.what = R.id.btn_end;
			//发送消息,自动将消息赋值给Handler对象对应的HandlerMessage中Message对象
			msg.sendToTarget();
			handler.postDelayed(runtestHandler, 1000);
		}
	};
}

 微笑微笑微笑微笑微笑

总结,通过学习HandlerThread与Handler,可以方便的操作一些多线程,便于UI界面等友好性设计。

微笑微笑微笑微笑微笑

备注:以上学习来自mars老师的教学视频和android sdk一些资料,欢迎大家查看。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值