http://lichen.blog.51cto.com/697816/486402


快一年没更新博客了, 这一年有些疲于奔命, 详细的在Q空间里再写吧. 因为转型做Android了, 开始新的学习历程了, 望此次重拾博客有新成长新感悟...

此文是关于Handler的。 Handler主要接受子线程发送的数据, 并用此数据配合主线程更新UI。 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) ,主线程为管理界面中的UI控件,进行事件分发, 比如说,你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。

这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程不是线程安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。这个时候,Handler就出现了,来解决这个复杂的问题。Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传递)Message对象(里面包含数据),把这些消息放入主线程队列中,配合主线程进行更新UI。

Handler一些特点:Handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行。

Handler中分发消息经常使用post(Runnable)和sendMessage(Message)方法。

先是sendMessage的例子:


   
  1. publicclass HandlerActivity extends Activity {

  2. private TextView textView;

  3. private MyHandler myHandler;

  4. private Button button;

  5. private ProgressBar progressBar;

  6. private MyThread m=new MyThread();

  7. /** Called when the activity is first created. */

  8. @Override

  9. publicvoid onCreate(Bundle savedInstanceState) {

  10. super.onCreate(savedInstanceState);

  11.   setContentView(R.layout.main);

  12.   textView=(TextView)findViewById(R.id.text);

  13.   button=(Button)findViewById(R.id.startButton);

  14.   progressBar=(ProgressBar)findViewById(R.id.bar);

  15.   progressBar.setMax(100);

  16.   button.setOnClickListener(new View.OnClickListener() {

  17. @Override

  18. publicvoid onClick(View arg0) {

  19.   myHandler=new MyHandler();

  20. new Thread(m).start();

  21.   System.out.println("onCreate--The Thread is: "+Thread.currentThread().getId());

  22.   }

  23.   });

  24.   }

  25. //在对UI进行更新时,执行时所在的线程为主UI线程

  26. class MyHandler extends Handler{//继承Handler类时,必须重写handleMessage方法

  27. public MyHandler(){

  28.   }

  29. public MyHandler(Looper l){

  30. super(l);

  31.   }

  32. @Override

  33. publicvoid handleMessage(Message msg) {//执行接收到的通知,此时执行的顺序是按照队列进行,即先进先出

  34.   System.out.println("Handler--The ThreadId is: "+Thread.currentThread().getId());

  35. super.handleMessage(msg);

  36.   Bundle b=msg.getData();

  37.   String textStr0=textView.getText().toString();

  38.   String textStr1=b.getString("textStr");

  39.   HandlerActivity.this.textView.setText(textStr0+" "+textStr1);//更改TextView中的值

  40. int barValue=b.getInt("barValue");HandlerActivity.this.progressBar.setProgress(barValue);//更改进度条当中的值

  41.   }

  42.   }

  43. //该线程将会在单独的线程中运行

  44. class MyThread implements Runnable{

  45. int i=1;

  46. @Override

  47. publicvoid run() {

  48. while(i<11){

  49.   System.out.println("Thread--The ThreadId is: "+Thread.currentThread().getId());

  50. try {

  51.   Thread.sleep(1000);

  52.   } catch (InterruptedException e) {

  53.   e.printStackTrace();

  54.   }

  55.   Message msg=new Message();

  56.   Bundle b=new Bundle();

  57.   b.putString("textStr", "线程运行"+i+"次");

  58.   b.putInt("barValue", i*10);

  59.   i++;

  60.   msg.setData(b);

  61.   HandlerActivity.this.myHandler.sendMessage(msg);//通过sendMessage向Handler发送更新UI的消息

  62.   }

  63.   }

  64.   }

  65.   }


简单的说,Activity的onCreate方法里启动一个线程,在这个线程的run方法里使用一个Message对象并使用Handler的sendMessage方法发送到队列中,最后在Activity里new一个Handler的内部类实现handMessage方法,使用这个方法把队列中的Message对象取出来以实现异步操作。

然后是post的例子,这里稍微说一下,直接使用new Handler().post(Runnable)这样的写法并没有新开线程,也就是说依然是在主线程中执行,相当于简单调用了线程的run方法而不是start方法。这个有人说是android的bug,解决方案是这样使用:


   
  1. HandlerThread handlerThread = new HandlerThread("myHandlerThread");

  2. handlerThread.start();

  3. handler = new Handler(handlerThread.getLooper());

来看一个完整的post例子:


   
  1. publicclass MyThread extends Activity {

  2. private Handler handler = null;

  3. @Override

  4. publicvoid onCreate(Bundle savedInstanceState) {

  5. super.onCreate(savedInstanceState);

  6. HandlerThread handlerThread = new HandlerThread("myHandlerThread");

  7. handlerThread.start();

  8. handler = new Handler(handlerThread.getLooper());

  9. handler.post(new MyRunnable());

  10. System.out.println("Oncreate---The Thread id is :"

  11. + Thread.currentThread().getId());

  12. setContentView(R.layout.main);

  13. }

  14. privateclass MyRunnable implements Runnable {

  15. publicvoid run() {

  16. System.out.println("Runnable---The Thread is running");

  17. System.out.println("Runnable---The Thread id is :"

  18. + Thread.currentThread().getId());

  19. try {

  20. Thread.sleep(6000);

  21. } catch (InterruptedException e) {

  22. // TODO Auto-generated catch block

  23. e.printStackTrace();

  24. }

  25. }

  26. }

  27. }

在这个demo中,用到了HandlerThread,在HandlerThread对象中可以通过getLooper方法获取一个Looper对象控制句柄,我们可以将其这个Looper对象映射到一个Handler中去来实现一个线程同步机制。于是就有以下结果;
1:控制台的输出:
Oncreate---The Thread id is :1
Runnable---The Thread is running
Runnable---The Thread id is :10
2:程序启动后,我们立刻看到main.xml中的内容。
这样就达到了多线程的结果。




更多相关文章

  1. 实战技巧:Android异步指南
  2. android 常用控件的使用 TextView EditTextView
  3. Android面试系列文章2018之Android部分HandlerThread机制篇
  4. [Android]Thread线程入门3--多线程
  5. Android日志(Log类)
  6. android - 为响应度而设计 - 开发文档翻译
  7. android 多任务多线程断点下载
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. SupperMMS
  2. 设置背景颜色
  3. SQLiteDatabaseTest
  4. GLSurfaceView使用之第二篇画三角形
  5. Android密码框中显示隐藏密码
  6. APK应用LOG保存
  7. android ViewPager学习笔记3
  8. iOS的Alerts与Android的Dialogs
  9. always on top button in android
  10. webView scroll滑动事件