android基础之消息机制

  最近任务比较少,基本没遇到什么特殊的要处理的东西,所以就写一写一些基础的东西,温故而知新是各位前辈们一项提倡的意见。

  消息机制是android学习的一个重要的模块,不过还是那句话,重要并不代表它很难。

  在android操作系统中存在着消息队列的操作,用消息队列可以完成主线程和子线程之间的消息传递,要完成这些线程的消息操作,则需要使用android.os包中LooperMessageHandle三个类。

  Message类:这个类的主要功能是进行消息的封装。在消息当中使用最多的是whatobj两个变量。

  1what变量指明一个Message所携带的是何种信息。

  2、而通过obj传递信息。

  Handler类:一般消息的操作则需要Handler完成。而操作Handler的对象就是主线程(UI线程)与子线程。

  Looper类:Looper类号称是消息的通道,使用Handler处理Message时,都是需要依靠一个Looper通道完成的,在一个Activity类中,会自动帮助用户启动Looper对象,而若是在自定义的类中,则需要用户手工调用Looper类中的若干方法。

  PS:关于LooperMessageHandler的另一种解释。

  行天曾看到一个很经典的解释,如果把Looper比喻成一个正在排队买票的队伍,那么每一个排队的人就是一个Message,而一个维护队伍的管理员就相当于一个Handler,管理员负责通知对外的人进到队列之中等待,也负责通知队列中的人离开队列。

  下面则通过一个滚动条的例子来具体了解一下这三个类的关系。

    

  

package com.example.progressbar;

import java.util.Timer;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.ProgressBar;
import android.widget.TextView;

public class WelcomeActivity extends Activity {

	private ProgressBar myProBar;//定义进度条
	private TextView info1;//定义信息1
	private Timer timer;//定义一个时间类
	private Handler myHandler;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		super.setContentView(R.layout.welcome);
		myProBar = (ProgressBar)this.findViewById(R.id.welcome_probar_myprobar);//实例化进度条
		info1 = (TextView)this.findViewById(R.id.welocome_text_show1);//实例化信息1
		myHandler = new MainHandler(this);
		timer = new Timer();//定义时间 子线程
		timer.schedule(new LoadTimerTask(myHandler), 0, 30);//立即开始,每隔30毫秒增长
	}
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		WelcomeActivity.this.myHandler.getLooper().quit();//结束队列
	}

	public TextView getInfo1() {
		return info1;
	}

	public void setInfo1(TextView info1) {
		this.info1 = info1;
	}


	public Timer getTimer() {
		return timer;
	}
	public void setTimer(Timer timer) {
		this.timer = timer;
	}
	public ProgressBar getMyProBar() {
		return myProBar;
	}
	public void setMyProBar(ProgressBar myProBar) {
		this.myProBar = myProBar;
	}

	
}

package com.example.progressbar;

import java.util.TimerTask;

import android.os.Handler;
import android.os.Message;

public class LoadTimerTask extends TimerTask{
	private int index = 0;//用于显示百分比
	private Handler handler;//定义handler用于传输百分比
	public LoadTimerTask(Handler handler) {
		// TODO Auto-generated constructor stub
		this.handler = handler;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		index ++;
		Message message = new Message();
		message.what = index;//将百分比放到message当中
		handler.sendMessage(message);//子线程将message放到handler中
		
	}
}


package com.example.progressbar;

import java.util.Timer;


import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainHandler extends Handler {
	private Activity activity;
	public MainHandler(Activity activity) {
		// TODO Auto-generated constructor stub
		this.activity = activity;
	}
	@Override
	public void handleMessage(Message msg) {
		// TODO Auto-generated method stub
		super.handleMessage(msg);
		int progress = msg.what;
		WelcomeActivity welcomeActivity = (WelcomeActivity)activity;
		TextView info1 = welcomeActivity.getInfo1();
		switch(progress)
		{
			case 20:
			{
				info1.setText("欢迎您                                   ");
				welcomeActivity.setInfo1(info1);
				break;
			}
			case 50:
			{
				info1.setText("欢迎您来到                          ");
				welcomeActivity.setInfo1(info1);
				break;
			}
			case 80:
			{
				info1.setText("欢迎您来到51比购网!");
				welcomeActivity.setInfo1(info1);
				break;
			}
			case 100:
			{
				Timer timer = welcomeActivity.getTimer();
				timer.cancel();
				welcomeActivity.setTimer(timer);
				System.out.println("timer被干掉");
			}
		}
		ProgressBar myProBar = welcomeActivity.getMyProBar();
		myProBar.setProgress(progress);
		welcomeActivity.setMyProBar(myProBar);//将数据设置进去
	}
}

  

  以上是一个老土的例子,原理也很简单。

  首先,主线程(UI线程)实例化handler对象以及调度器,之后调用调度器的实现类(子线程)。

  其次,在子线程中实现消息(Message)的生成,并用Handler将消息返回到主线程。

  再次,在自定义的handler类当中进行数据的处理,并控制ProgressBar以及TextView的处理。

  不过,今天行天要讲的重点根本就不是这个故事。大笑

  在实际开发中,当我们用到消息控制的时候会有千奇百怪的问题,比如说细心的同学会问,为什么一定要在子线程当中把消息传给Handler然后在处理主线程的组件,干嘛不在子线程当中直接处理控制住线程的组件。

 简单修改一下代码。

	@Override
	public void run() {
		// TODO Auto-generated method stub
		index ++;
		Message message = new Message();
		message.what = index;//将百分比放到message当中
		handler.sendMessage(message);//子线程将message放到handler中
		
		WelcomeActivity welcomeActivity = (WelcomeActivity)activity;
		TextView textView = welcomeActivity.getInfo1();
		textView.setText(index);
		welcomeActivity.setInfo1(textView);
	}

  结果就会发现报错:
  
  android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
  
  原因很简单,在android当中规定, 子线程不能更新主线程的UI组件。
  

  问题2:当时我看到这段代码的时候,我第一个反应就是,Looper呢?Looper怎么没了,难不成这就是传说中的配角组件?

  答:其实以上的这段代码并非我们所看到的表面现象,其中省略了一些东西。因为我们现在是由Activity直接发送消息的,所以在Handler的子类中会自动帮助用户创建好要操作的Looper对象。如果用户使用自定义的线程类,就要由用户自己进行Looper对象的维护操作了。

  添加一个ChildThread类用作测试

package com.example.progressbar;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public class ChildThread implements Runnable{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Message message = new Message();
		message.what = 8080;
		Looper.prepare();
		Handler childHandler = new Handler(){
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				super.handleMessage(msg);
				System.out.println(msg.what);
			}
		};
		childHandler.sendMessage(message);
		Looper.loop();

	}

}




  结果很正常。

  在本段程序中最重要的部分就是Looper对象操作的prepare()和loop()方法,如果没有这两方法,将无法通过子线程创建Looper,也就无法传递消息。

  

 结果就会报这种错误。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值