你的位置:首页 > 操作系统

[操作系统]Android之Handler探索


Handler背景理解: 

 Handler被最多的使用在了更新UI线程中,但是,这个方法具体是什么样的呢?我在这篇博文中先领着大家认识一下什么是handler以及它是怎么样使用在程序中,起着什么样的作用。

  示例说明:

    首先先建立两个按钮:一个是start按钮,作用是开启整个程序。另一个是终止按钮end,作用是结束整个的程序。这两个按钮的相互对比就会让大家明白Handlerd的基本的工作原理。

运行结果截图:

MainActivity.class

package com.example.testhandler;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity {		private Button start,end;	//实例化一个handler对象	private Handler handler = new Handler();	//开启一个新的线程:开启线程有两种方式,一种是使用普通的Thread方法,另一个中是使用Runnable方法	Runnable update = new Runnable() {				@Override		public void run() {			System.out.println("update");			handler.postDelayed(update, 3000);		}	};		@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		start = (Button)this.findViewById(R.id.btn_start);		end = (Button)this.findViewById(R.id.btn_end);				start.setOnClickListener(new OnClickListener() {						@Override			public void onClick(View v) {				//加入到队列中去执行				handler.post(update);			}		});				end.setOnClickListener(new OnClickListener() {						@Override			public void onClick(View v) {				//将消息移除队列中去				handler.removeCallbacks(update);			}		});			}}

  当点击Start按钮时的效果图如下:

当点击end按钮时的效果图如下:

注意:

  Handler中的post方法并没有开启一个新的线程,他的操作是在主线程中执行的。下面咱们就来验证一下这个观点。

  首先先贴一下运行截图:

  

  等过10s之后的运行结果是:

  

这里只是测试一下handler的post()方法是否是在主线程中进行的。所以没有布局。

设计思路:

在主线程中输出主线程当前的ID和Name,然后使用Runnable方式新建一个线程,在这个新线程中让程序睡眠10s,将这个线程使用Handler的post()方法发送到主线程中,看是否是执行异步加载。也就是验证handler是否是异步加载方式。结论:Handler不是异步加载方式。

MainActivity:

package com.example.handlertest1;import android.os.Bundle;import android.os.Handler;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity {	private Handler mhandler = new Handler();		@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		//将多线程发送到消息队列中		mhandler.post(r);		//不会立刻加载界面,这说明了handler并不是开辟了一个新的线程而是在主线程中进行的。		setContentView(R.layout.activity_main);		System.out.println("Activity-->"+Thread.currentThread().getId());		System.out.println("Activity-->"+Thread.currentThread().getName());	}	Runnable r = new Runnable() {		public void run() {			System.out.println("Handler--->"+Thread.currentThread().getId());			System.out.println("handler--->"+Thread.currentThread().getName());			try {				Thread.sleep(10000);			} catch (Exception e) {				e.printStackTrace();			}		}	};	}

LogCat文件的输出:

 

在这里通过ID号很明显的看出这不是执行的是多线程加载

在上面的主线程中重新新建一个线程则实现了多线程的加载:

将上面的onCreate()中的代码替换为:

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    //将多线程发送到消息队列中//    mhandler.post(r);    //不会立刻加载界面,这说明了handler并不是开辟了一个新的线程而是在主线程中进行的。    setContentView(R.layout.activity_main);    //这是另外开启了一个新的线程,会发现这里输出的速率会比上次的快很多    Thread t = new Thread(r);    t.start();    System.out.println("Activity-->"+Thread.currentThread().getId());    System.out.println("Activity-->"+Thread.currentThread().getName());  }

效果截图如下:

LogCat文件中的输出结果截图为:

 

在这里通过ID号很明显的看出了这是执行了多线程加载。

  Handler要想开辟一个新的线程需要使用HanderThread()方法。下面就是HandlerThread()的用法:

设计思路:

  通过使用handler方法传输数据,然后使用HandlerThread,实现了使用Looper来处理消息队列的功能。输出当前的Activity的ID和Name,以及Handler的ID和Name以及传输的数据

代码如下:

 1 package com.example.handlertest1; 2  3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.HandlerThread; 7 import android.os.Looper; 8 import android.os.Message; 9 10 public class HandlerTest2 extends Activity{11 12   @Override13   protected void onCreate(Bundle savedInstanceState) {14     super.onCreate(savedInstanceState);15     setContentView(R.layout.activity_main);16     17     //打印当前线程的ID和当前线程的名字18     System.out.println("Activity-->"+Thread.currentThread().getId());19     System.out.println("Activity-->"+Thread.currentThread().getName());20     21     //HandlerThread是以键值对的形式进行存储的,这里的handler_thread就是该handler的键名22     //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能。这是有android来提供的并不是java中的Thread提供23     HandlerThread handlerthread = new HandlerThread("handler_thread");24     handlerthread.start();25     MyHandler myhandler = new MyHandler(handlerthread.getLooper());26     Message msg = myhandler.obtainMessage();27     //传送多的数据的时候使用的setData()方法,使用Bundle()将数据包装28     Bundle b = new Bundle();29     b.putInt("age", 20);30     b.putString("name", "张三");31     msg.setData(b);32     //将消息发送给目标,目标就是生成该msg对象的handler33     msg.sendToTarget();34     35   }36   37   class MyHandler extends Handler{38     39     public MyHandler(){40       41     }42     public MyHandler(Looper looper){43       super(looper);44     }45     46     @Override47     public void handleMessage(Message msg) {48       Bundle b = msg.getData();49       int age = b.getInt("age");50       String name = b.getString("name");51       System.out.println("age is"+age+",name"+name);52       System.out.println("Handler--->"+Thread.currentThread().getId());53       System.out.println("Handler--->"+Thread.currentThread().getName());54       System.out.println("handlermessage");55     }56     57   }58   59 }

好了,就这么多了,具体的关于Handler、Looper、Message三者的关系,参考http://blog.csdn.net/lmj623565791/article/details/38377229个人感觉不错




江苏旅游线路报价江苏旅游攻略大全江苏旅游路线推荐江苏自驾游攻略江苏旅游线路大全如果你来 我才不会告诉你郑州四季要这么玩 乐昌龙王潭安在哪里?龙王潭在什么地方? 乐昌龙王潭图片?韶关龙王潭漂亮吗? 相约红河绿春享受长古宴 品味曲靖罗平滇王老窖珍品 香溪堡官网,惠州龙门香溪堡旅游区官方网站。 信宜大仁山有公交车吗?到大仁山坐什么车去? 信宜怎么样去大仁山?茂名信宜大仁山交通线路? 信宜大仁山网上购票多少钱?大仁山门票预订? 恩平岑洞峡谷详细路线?岑洞大峡谷漂流怎么去? 恩平岑洞峡谷具体位置?岑洞大峡谷漂流怎么走? 恩平岑洞峡谷在什么地方?岑洞大峡谷漂流地址? 赣江源漂流需要带什么?赣州石城赣江源漂流需要带雨衣吗? 鼓浪屿上咖啡店哪家实惠又好喝? 坐飞机去海南三亚,请问可以带化妆品吗? 12月份三亚的天气怎样?要穿什么衣服? 感恩节做什么好? 553-0006-803F Datasheet 553-0006-803F Datasheet 553-0006-804 Datasheet 553-0006-804 Datasheet 553-0006-804F Datasheet 553-0006-804F Datasheet 杭州到香港旅游价格 杭州到香港旅游价格 杭州到香港旅游价格 浙江到香港澳门旅游价格 浙江到香港澳门旅游价格 浙江到香港澳门旅游价格 牡丹江到香港游价格 牡丹江到香港游价格 牡丹江到香港游价格