最近学习Android,学习的时候会用Java的一些机制去理解,但是往往还是有些区别的。


下面我们来看看Android下面的线程使用方法,这里通常会用到Handler。


Handler的作用就是一个队列,先进先出,实现了异步机制。


下面是这个工程的main.xml配置文件:(两个例子的使用同一个xml)

[java] view plain copy print ?
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <ProgressBar
  8. android:id="@+id/bar"
  9. style="?android:attr/progressBarStyleHorizontal"
  10. android:layout_width="200dp"
  11. android:layout_height="wrap_content"
  12. android:visibility="gone"
  13. />
  14. <Button
  15. android:id="@+id/startButton"
  16. android:layout_width="fill_parent"
  17. android:layout_height="wrap_content"
  18. android:text="start"
  19. />
  20. </LinearLayout>


[java] view plain copy print ?
  1. packagecom.cyl;
  2. importandroid.app.Activity;
  3. importandroid.os.*;
  4. importandroid.widget.*;
  5. importandroid.view.View;
  6. importandroid.view.View.OnClickListener;
  7. publicclassProgressBarHandlerextendsActivity{
  8. privateProgressBarbar;
  9. privateButtonstart;
  10. privateHandlerprogressHandler;
  11. RunnableprogressThread;
  12. @Override
  13. publicvoidonCreate(BundlesavedInstanceState){
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.main);
  16. //测试当前Activity线程
  17. //打印的结果是:ActivityThread:1
  18. System.out.println("ActivityThread:"+Thread.currentThread().getId());
  19. bar=(ProgressBar)this.findViewById(R.id.bar);
  20. start=(Button)this.findViewById(R.id.startButton);
  21. //实现了Handler的内部类
  22. progressHandler=newHandler(){
  23. @Override
  24. publicvoidhandleMessage(Messagemsg){
  25. bar.setProgress(msg.arg1);
  26. //经过证明Thread均是同一线程。
  27. //打印的结果是:HandlerThread:1
  28. System.out.println("HandlerThread:"+Thread.currentThread().getId());
  29. progressHandler.post(progressThread);
  30. //模拟在90%时停止,removeCallbacks移除线程不能放在Runnable中,否则可能会出现Bug,无法移除。
  31. if(msg.getData().getInt("percent")>=90){
  32. progressHandler.removeCallbacks(progressThread);
  33. }
  34. }
  35. };
  36. //当在程序启动的时候就调用Handler进行加载处理
  37. //并且线程的执行时间很长,且不可预测,那么程序就会处于一个假死状态
  38. //progressHandler.post(progressThread);
  39. start.setOnClickListener(newOnClickListener(){
  40. @Override
  41. publicvoidonClick(Viewv){
  42. bar.setVisibility(ProgressBar.VISIBLE);
  43. progressHandler.post(progressThread);
  44. }
  45. });
  46. //实现了Runnable的内部类
  47. progressThread=newRunnable(){
  48. intpercent=0;
  49. @Override
  50. publicvoidrun(){
  51. percent+=5;
  52. //打印的结果是:RunnableThread:1
  53. System.out.println("RunnableThread:"+Thread.currentThread().getId());
  54. //通过Message对象传递参数
  55. Messagemsg=newMessage();
  56. Bundlebundle=newBundle();
  57. bundle.putInt("percent",percent);
  58. msg.setData(bundle);
  59. progressHandler.sendMessage(msg);
  60. try{
  61. System.out.println("sleep...");
  62. Thread.sleep(1000);
  63. //当在onCreate方法开始就调用progressHandler.post()时,我们设置时间足够长,模拟假死状态。
  64. //主线程处于等待状态,界面无法显示。
  65. //Thread.sleep(10000);
  66. System.out.println("wakeup...");
  67. }catch(Exceptione){
  68. e.printStackTrace();
  69. }
  70. }
  71. };
  72. }
  73. }


在上面的例子中,Thread使用的是同一个,按照Java的常理应该是不同的,但是这里确实是同一个,大家可以自己测试下。


Handler与主线程是同一线程时,如果程序在设计的时候需要线程初始化较长时间或者下载文件,这种情况下,主线程是出于等待状态的,甚至出现假死现象。


在cmd100.com的视频讲解中,mars老师也讲的很清楚了,我大部分是参考其源代码再做修改。


解决办法是是用HandlerThread类来创建独立于主线程的新线程,实现异步机制,不会影响到主线程的运行。

解决代码如下

[java] view plain copy print ?
  1. packagecom.cyl;
  2. importandroid.app.Activity;
  3. importandroid.os.*;
  4. importandroid.widget.*;
  5. importandroid.view.View;
  6. importandroid.view.View.OnClickListener;
  7. publicclassProgressBarHandlerThreadextendsActivity{
  8. /**Calledwhentheactivityisfirstcreated.*/
  9. ProgressBarbar;
  10. Buttonstart;
  11. MyHandlermyHandler;
  12. RunnableprogressThread;
  13. @Override
  14. publicvoidonCreate(BundlesavedInstanceState){
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.main);
  17. System.out.println("ActivityThread:"+Thread.currentThread().getId());
  18. bar=(ProgressBar)this.findViewById(R.id.bar);
  19. start=(Button)this.findViewById(R.id.startButton);
  20. //使用HandlerThread来实现真正的异步线程,不会与主线程公用线程了。
  21. HandlerThreadhandlerThread=newHandlerThread("handler_thread");
  22. //使用getLooper()方法之前,先调start()方法
  23. handlerThread.start();
  24. myHandler=newMyHandler(handlerThread.getLooper());
  25. start.setOnClickListener(newOnClickListener(){
  26. @Override
  27. publicvoidonClick(Viewv){
  28. bar.setVisibility(ProgressBar.VISIBLE);
  29. myHandler.post(progressThread);
  30. }
  31. });
  32. //实现了Runnable的内部类
  33. progressThread=newRunnable(){
  34. intpercent=0;
  35. @Override
  36. publicvoidrun(){
  37. percent+=5;
  38. //打印的结果是:ActivityThread:8
  39. System.out.println("RunnableThread:"+Thread.currentThread().getId());
  40. //通过Message对象传递参数
  41. Messagemsg=newMessage();
  42. Bundlebundle=newBundle();
  43. bundle.putInt("percent",percent);
  44. msg.setData(bundle);
  45. myHandler.sendMessage(msg);
  46. try{
  47. Thread.sleep(1000);
  48. }catch(Exceptione){
  49. e.printStackTrace();
  50. }
  51. }
  52. };
  53. }
  54. classMyHandlerextendsHandler{
  55. publicMyHandler(Looperlooper){
  56. super(looper);
  57. }
  58. @Override
  59. publicvoidhandleMessage(Messagemsg){
  60. bar.setProgress(msg.arg1);
  61. //打印的结果是:MyHandlerThread:8
  62. System.out.println("MyHandlerThread:"+Thread.currentThread().getId());
  63. myHandler.post(progressThread);
  64. if(msg.arg1>=90){
  65. myHandler.removeCallbacks(progressThread);
  66. }
  67. }
  68. }
  69. }

更多相关文章

  1. Android开发秘籍学习笔记(三)
  2. android 的消息处理
  3. Android的消息机制(一)——概述
  4. Android(安卓)Gson
  5. Android中的线程与线程池
  6. Android(安卓)面试总结
  7. 在Service中新开线程和直接新开线程的区别与意义
  8. 【Android】网络通讯
  9. Android(安卓)- Looper.prepare()和Looper.loop() —深入讲解

随机推荐

  1. Android通过startService播放背景音乐简
  2. Cordova+Vue整合到android studio上实现
  3. Android(安卓)Studio代码调试技巧篇
  4. android生命周期()
  5. 如何使Android应用程序获取系统权限
  6. Android系列教程之七:EditText使用详解-包
  7. android 按钮水波纹效果
  8. 最简单的走马灯实现
  9. android sqlite 操作
  10. Android开发秘籍学习笔记(一)