Handler机制实例

Handler机制原理推荐看这篇博客:http://blog.csdn.net/jiayi_yao/article/details/51082073

实例,请看本文。


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cctvjiatao.handlerdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity android:name=".SendMsgAct"></activity>
        <activity android:name=".PostDelayedAct"></activity>
        <activity android:name=".SendMsgProgressbarAct"></activity>
        <activity android:name=".IsSameThreadAct"></activity>
        <activity android:name=".SendMsgLooperAct"></activity>
    </application>

</manifest>

MainActivity.java

package com.cctvjiatao.handlerdemo;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/**
 * Handler机制原理详见:http://blog.csdn.net/jiayi_yao/article/details/51082073
 */
public class MainActivity extends Activity {

	private final String TAG = getClass().getSimpleName();
	private Context context;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		context = this;
		setContentView(R.layout.activity_main);
		initView();
	}

	private void initView() {
	    Button btn1 = (Button) findViewById(R.id.btn1);
	    Button btn2 = (Button) findViewById(R.id.btn2);
	    Button btn3 = (Button) findViewById(R.id.btn3);
	    Button btn4 = (Button) findViewById(R.id.btn4);
	    Button btn5 = (Button) findViewById(R.id.btn5);
	    
	    btn1.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startActivity(new Intent(context, SendMsgAct.class));
				
			}
		});
	    
	    btn2.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startActivity(new Intent(context, PostDelayedAct.class));
				
			}
		});
	    
	    btn3.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startActivity(new Intent(context, SendMsgProgressbarAct.class));
				
			}
		});
	    
	    btn4.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startActivity(new Intent(context, IsSameThreadAct.class));
				
			}
		});
	    
	    btn5.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startActivity(new Intent(context, SendMsgLooperAct.class));
				
			}
		});
    }

}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.cctvjiatao.handlerdemo.MainActivity" >

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="sendMsg" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PostDelayedAct" />

    <Button
        android:id="@+id/btn3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SendMsgProgressbarAct" />
    
    <Button
        android:id="@+id/btn4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="IsSameThreadAct" />

    <Button
        android:id="@+id/btn5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SendMsgLooperAct" />

</LinearLayout>

SendMsgAct.java

package com.cctvjiatao.handlerdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Button;

/**
 * @作者: jiatao
 * @修改时间:2016-4-10 下午10:55:26
 * @包名:com.cctvjiatao.handlerdemo
 * @文件名:SendMsgAct.java
 * @版权声明:www.cctvjiatao.com
 * @功能: 不断变化的按钮
 */
public class SendMsgAct extends Activity {

	private final String TAG = getClass().getSimpleName();
	private MyHandler mMyHandler;
	private Button btn_variable;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.act_sendmsg);
		btn_variable = (Button) findViewById(R.id.btn_variable);

		mMyHandler = new MyHandler();

		MyThread m = new MyThread();
		new Thread(m).start();
	}

	class MyHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			Log.e(TAG, "handleMessage...");
			Bundle b = msg.getData();
			String btnStr = b.getString("name");
			btn_variable.append(btnStr);
		}
	}

	class MyThread implements Runnable {

		@Override
		public void run() {
			while (true) {
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				Message msg = new Message();
				Bundle b = new Bundle();
				b.putString("name", "Monkey");
				msg.setData(b);
				SendMsgAct.this.mMyHandler.sendMessage(msg);
				Log.e(TAG, "sendMessage...");
			}
		}

	}

}

PostDelayedAct.java

package com.cctvjiatao.handlerdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

/**
 * @作者: jiatao
 * @修改时间:2016-4-10 下午11:55:26
 * @包名:com.cctvjiatao.handlerdemo
 * @文件名:PostDelayedAct.java
 * @版权声明:www.cctvjiatao.com
 * @功能: Handler.postDelayed + Runnable 
 * 		这个例子是最简单的介绍handler的使用:是将handler绑定到它所建立的线程中.
 */
public class PostDelayedAct extends Activity {

	private final String TAG = getClass().getSimpleName();
	private TextView tv_msg;
	private Button btn_start, btn_end;
	
	Handler handler = new Handler();
	Runnable rb = new Runnable(){
		public void run() {
			//线程每次执行时输出"UpdateThread..."文字,且自动换行
			tv_msg.append("\nUpdateThread...");
			//延时3s后又将线程加入到线程队列中
			handler.postDelayed(rb, 3000);//可以尝试注释本行代码,观察变化
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.act_postdelayed);
		initView();
	}

	private void initView() {
		tv_msg = (TextView) findViewById(R.id.tv_msg);
		btn_start = (Button) findViewById(R.id.btn_start);
		btn_end = (Button) findViewById(R.id.btn_end);
		
		btn_start.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				 //将线程接口立刻送到线程队列中
				handler.post(rb);
				Log.e(TAG, "start...");
			}
		});
		
		btn_end.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//将线程接口从线程队列中移除
				handler.removeCallbacks(rb);
				Log.e(TAG, "end...");
			}
		});
	    
    }

}

SendMsgProgressbarAct.java

package com.cctvjiatao.handlerdemo;

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;
import android.widget.TextView;

/**
 * @作者: jiatao
 * @修改时间:2016-4-10 下午11:55:26
 * @包名:com.cctvjiatao.handlerdemo
 * @文件名:SendMsgProgressbarAct.java
 * @版权声明:www.cctvjiatao.com
 * @功能: 例子中用到了handler的消息队列机制,
 * 		即通过handler中一个线程向消息队列中用sendMessage方法发送消息,发送的消息当然可以用来传递参数。
 * 		在handler中用handleMessage来处理消息,处理方法是获得消息队列中的消息参数,用这些参数来完成另外一些功能。
 */
public class SendMsgProgressbarAct extends Activity {

	private final String TAG = getClass().getSimpleName();
	private ProgressBar pb_handler;
	private Button btn_start;
	
	//创建一个handler,内部完成处理消息方法
	Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			Log.e(TAG, "sendMessage...");
			//显示进度条
			pb_handler.setProgress(msg.arg1);
			//重新把进程加入到进程队列中
			handler.post(rb);//注释本行代码,观察变化
		};
	};
	
	Runnable rb = new Runnable(){
		int i = 0;
		public void run() {
			i += 10;
			//首先获得一个消息结构
			Message msg = handler.obtainMessage();
			//给消息结构的arg1参数赋值
			msg.arg1 = i;
			//延时1s,java中的try+catch用来排错处理
			try {
	            Thread.sleep(1000);
            } catch (InterruptedException e) {
	            e.printStackTrace();
            }
			//把消息发送到消息队列中
			handler.sendMessage(msg);
			Log.e(TAG, "sendMessage...");
			if(i == 100){
				//把线程从线程队列中移除
				handler.removeCallbacks(rb);
			}
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.act_progressbar);
		initView();
	}

	private void initView() {
		pb_handler = (ProgressBar) findViewById(R.id.pb_handler);
		btn_start = (Button) findViewById(R.id.btn_start);
		
		btn_start.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				pb_handler.setVisibility(View.VISIBLE);
				 //将线程接口立刻送到线程队列中
				handler.post(rb);
				Log.e(TAG, "start...");
			}
		});
		
    }

}

IsSameThreadAct.java

package com.cctvjiatao.handlerdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

/**
 * @作者: jiatao
 * @修改时间:2016-4-10 下午11:55:26
 * @包名:com.cctvjiatao.handlerdemo
 * @文件名:IsSameThreadAct.java
 * @版权声明:www.cctvjiatao.com
 * @功能: 验证仅使用handler的post方法是否处于同一个线程
 * 		例子PostDelayedAct和例子SendMsgProgressbarAct表面上看handler使用了post方法启动了runnbale,
 * 		其实启动的线程和activity主线程是同一个线程,因为它只是运行了线程的run方法,而不是start方法。
 */
public class IsSameThreadAct extends Activity {

	private final String TAG = getClass().getSimpleName();
	
	//新建一个handler
	Handler handler = new Handler();
	
	Runnable rb = new Runnable(){
		public void run() {
			//打印新建线程信息
			Log.e(TAG, "handler_id---->"+Thread.currentThread().getId());
			Log.e(TAG, "handler_name---->"+Thread.currentThread().getName());
			//延时10s,为了观察主界面中内容出现的时间
			try {
	            Thread.sleep(3000);
            } catch (InterruptedException e) {
	            e.printStackTrace();
            }
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//将runnable加载到handler的线程队列中去
		handler.post(rb);
		/*Thread t = new Thread(rb);
		t.start();*/
		setContentView(R.layout.act_postdelayed);
		//打印activtiy线程信息
		Log.e(TAG, "activity_id---->"+Thread.currentThread().getId());
		Log.e(TAG, "activity_name---->"+Thread.currentThread().getName());
	}

}
/**
 * 结果说明这两个线程确实是同一线程,并且可以看出主界面中的文字大概过了10s才显示出来,
 * 因为语句setContentView(R.layout.activity_main);放在了handler的post启动语句后面,
 * 而handler绑定的线程中又延时了10s,所以同时也证明了只有是同一个线程才会出现这种情况。
 */

/**
 * 如果把语句:
 * 		handler.post(rb);
 * 换成:
 * 		Thread t = new Thread(rb);
 * 		t.start();
 * 其它的不变,则程序运行时主界面内容立刻就显示出来了,且打印日志为。。。
 * 这两者都说明这样绑定的线程与它所在的activity线程就不是同一个线程了。
 */

SendMsgLooperAct.java

package com.cctvjiatao.handlerdemo;

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;
import android.widget.TextView;

/**
 * @作者: jiatao
 * @修改时间:2016-4-10 下午11:55:26
 * @包名:com.cctvjiatao.handlerdemo
 * @文件名:SendMsgLooperAct.java
 * @版权声明:www.cctvjiatao.com
 * @功能: 学会使用怎样在新线程中处理消息的方法
 *      1)这个例子将学会怎样不使用runnable来启动一个线程,而是用HandlerThread的looper来构造一个handler,
 *      	然后该handler自己获得消息,并传递数据,然后又自己处理消息,当然这是在另一个线程中完成的。
 *      2)消息结构中传递简单的整型可以采用它的参数arg1和arg2,或者传递一些小的其它数据,
 *      	可以用它的object,该object可以是任意的对象。
 *      	当需要传送比较大的数据是,可以使用消息的setData方法,该方法需要传递一个Bundle的参数。
 *      	Bundle中存放的是键值对的map,只是它的键值类型和数据类型比较固定而已。
 */
public class SendMsgLooperAct extends Activity {

	private final String TAG = getClass().getSimpleName();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.act_postdelayed);
		Log.e(TAG, "activity_ID---->" + Thread.currentThread().getId());
		Log.e(TAG, "activity_Name---->" + Thread.currentThread().getName());
		
		// 新建一个HanderThread对象,该对象实现了用Looper来处理消息队列的功能		
		HandlerThread handler_thread = new HandlerThread("handler_thread");
		handler_thread.start();
		
		// MyHandler类是自己继承的一个类,这里采用hand_thread的Looper来初始化它
		MyHandler my_handler = new MyHandler(handler_thread.getLooper());
		// 获得一个消息msg
		Message msg = my_handler.obtainMessage();
		// 采用Bundle保存数据,Bundle中存放的是键值对的map,只是它的键值类型和数据类型比较固定而已
		Bundle b = new Bundle();
		b.putString("whether", "晴天");
		b.putInt("temperature", 34);
		msg.setData(b);
		// 将msg发送到自己的handler中,这里指的是my_handler,调用该handler的HandleMessage方法来处理该mug
		msg.sendToTarget();
	}

	class MyHandler extends Handler {
		// 空的构造函数
		public MyHandler() {
			
		}
		// 以Looper类型参数传递的函数,Looper为消息泵,不断循环的从消息队列中得到消息并处理,
		// 因此,每个消息队列都有一个Looper,因为Looper是已经封装好了的消息队列和消息循环的类
		public MyHandler(Looper looper) {
			// 调用父类的构造函数
			super(looper);
		}

		@Override
		public void handleMessage(Message msg) {
			Log.e(TAG, "Handler_ID---->" + Thread.currentThread().getId());
			Log.e(TAG, "Handler_Name---->" + Thread.currentThread().getName());
			// 将消息中的bundle数据取出来
			Bundle b = msg.getData();
			String whether = b.getString("whether");
			int temperature = b.getInt("temperature");
			Log.e(TAG, "Handler_ID---->" + "whether= " + whether + " ,temperature= " + temperature);
		}

	}
}

act_sendmsg.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.cctvjiatao.handlerdemo.SendMsgAct" >

    <Button
        android:id="@+id/btn_variable"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="多变的按钮" />

</LinearLayout>

act_postdelayed.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_msg"
        android:layout_width="fill_parent"
        android:layout_height="400dip"
        android:text="@string/hello_world"/>

    <Button
        android:id="@+id/btn_start"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="开始" />

    <Button
        android:id="@+id/btn_end"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="结束" />

</LinearLayout>

act_progressbar.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/btn_start"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="开始" />

    <ProgressBar
        android:id="@+id/pb_handler"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="100dip"
        android:layout_alignParentTop="true"
        android:visibility="gone" />

</RelativeLayout>


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值