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 @Override 13 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对象的handler 33 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 @Override 47 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个人感觉不错