Android入门--Handler的使用

第一篇博文啊,学习编程一年了,迷茫混乱中走来,大致确定了学习的方向,这阵子突然发现以前学过的好多些东西都差不多忘了,想要复习才发现手头没有笔记,好好反思下以前的学习方法,计算机方面的学习确实很难做到写笔记,但没有笔记又不能总结复习,于是找到了博客这东西,以前在学习过程中遇到问题,百度一下,很多技术性的解答都出自博客,从那些博客中确实学到很多,也解决了很多问题,在此表示感谢。话说回来,既然准备走上IT这条路,养成一个好的习惯是很有必要的,于是准备写博客,帮助自己复习记忆,也可以给别人一些帮助。。。下面开始第一篇博客!

Handler的使用

“Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行”。对于这句话的理解,真是费了很大劲啊,现在来说说这句话的意思,就是对于主界面中的控件的操作,比如Button上的文字改变,TextView中的内容改变,显示Toast,ProgressBar更新等涉及控件改变的操作,都必须在UI线程中进行,那要是我在一个新线程中进行了某些操作,操作完成了,想要弹出一个Toast告诉用户,这时是不能在新线程中直接调用Toast的,于是Handler的概念就出来了,通过发送Message信息,在UI线程中调用Handler对象接收Message消息,并根据收到的消息内容进行不同的操作。这样就解决了不能在UI线程意外的线程中改变UI控件。

下面是Handler的具体用法

一、Handler的定义:
    Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用。比如可以用handler发送一个message,然后在handler的线程中来接收、处理该消息,以避免直接在UI主线程中处理事务导致影响UI主线程的其他处理工作,Android提供了Handler作为主线程和子线程的纽带;也可以将handler对象传给其他进程,以便在其他进程中通过handler给你发送事件;还可以通过handler的延时发送message,可以延时处理一些事务的处理。
通常情况下,当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发。如果此时需要一个耗时的操作,例如:联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,会收到Android系统的一个错误提示"强制关闭". 
这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,但是当子线程中有涉及到操作UI的操作时,就会对主线程产生危险,也就是说,更新UI只能在主线程中更新,在子线程中操作是危险的. 这个时候,Handler就出现了来解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传递)Message对象,(里面包含数据), 把这些消息放入主线程队列中,配合主线程进行更新UI。

二、Handler的特点
        handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程), 也就是说Handler对象初始化后,就默认与对它初始化的进程的消息队列绑定,因此可以利用Handler所包含的消息队列,制定一些操作的顺序。
 
三、Handler中分发消息的一些方法
        post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
            post类方法允许你排列一个Runnable对象到主线程队列中
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)
           sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

四、小例子

package com.example.testhandler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**
 * @author cen
 *Handler可以传Message对象,也可以传Runnable对象,就是线程对象
 *其中对于Message对象,是调用sendMessage()方法,对于Runnable对象就是调用post()方法
 *Handler的使用方法:
 *1.首先在子线程中创建Message类的对象,并调用obtain方法,然后进行赋值,然后调用sendMessage()方法
 *2.在主线程中创建新的Handler对象,调用handleMessage()方法用于接收子线程传来的消息
 *关于Looper:
 *Looper是消息队列,默认只在主线程中创建,在其他线程中需要调用Looper.prepare方法创建消息队列,然后调用Looper.loop方法进入消息循环
 *Handle只是针对那 些有Looper的线程,不管是UI线程还是子线程,只要你有Looper,我就可以往你的消息队列里面添加东西,并做相应的处理。
 
 */
public class MainActivity extends Activity {

	Handler mHandler;
	private static final int downloading=1;
	private static final int download=100;
	
	ProgressBar mprogressBar;
	TextView mtextview;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();//初始化的方法
		setListener();//设置按钮监听事件
		initHandler();//初始化Handler的方法
	}
	
	private void initHandler() {
		mHandler=new Handler(){
			@Override
			public void handleMessage(Message msg) {
					switch (msg.what) {
					case downloading:
						mtextview.setText(msg.arg1+"%");
						mprogressBar.setProgress(msg.arg1);//设置进度条里的值为每次循环递增的值
						break;
					case download:
						Toast.makeText(MainActivity.this, "下载完成", 0).show();
						break;
					}
			}
		};
	}
	private void setListener() {
		//设置监听事件的内容就是加一个按钮的时间,然后在事件里添加一个线程
		findViewById(R.id.btdowmload).setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				new Thread(){//新建一个线程
					public void run() {
						for (int i = 0; i < 100; i++) {
							SystemClock.sleep(500);//每次循环之前都休眠500毫秒
							
							Message msg=Message.obtain();//Message对象,获取消息
							msg.what=downloading;//定义消息码,就理解成唯一标识码,为了和主线程的Handler一一对应用的
							msg.arg1=i;//设置msg的值
							mHandler.sendMessage(msg);//发送消息
						}
						Message msg=Message.obtain();//循环结束后发送,这里没有发送任何值,只发送了一个标识码
						msg.what=download;//设置标识码为download
						mHandler.sendMessage(msg);
					};
				}.start();
			}
		});
	}

	private void initView() {
		// TODO Auto-generated method stub
		mprogressBar=(ProgressBar) findViewById(R.id.progressbar);
		mtextview=(TextView) findViewById(R.id.tvprogress);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值