博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 学习 笔记_02. handler的使用
阅读量:7087 次
发布时间:2019-06-28

本文共 6186 字,大约阅读时间需要 20 分钟。

     大家知道,Handler在Android中主要是负责发送和处理消息。它的主要用途大致是下面两个:
 
  1)按计划发送消息或执行某个Runnanble;
 
  2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程)
 
   学写一下,在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理。在实例化Handler的时候,只要有Handler的指针,任何线程也都可以sendMessage。
   
       Handler对于Message的处理是异步处理的。一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)。
 
       根据对视频的学习写了一个通过Button控件启动进度条(类似于下载等操作)的程序,简单介绍一下,有两个Button控件,一个是开始,点击之后会显示一个进度条以每次十分之一的进度进行(一开始是隐藏的),另一个是停止,可以中断进度。
 
 
      
 
java代码:
1 package zzl.handleactivity;  2   3 import android.app.Activity;  4 import android.os.Bundle;  5 import android.os.Handler;  6 import android.os.Message;  7 import android.view.Gravity;  8 import android.view.View;  9 import android.view.View.OnClickListener; 10 import android.widget.Button; 11 import android.widget.ProgressBar; 12 import android.widget.Toast; 13  14 public class Handler_01 extends Activity { 15      16     //声明变量 17     private Button startButton=null; 18     private Button endButton=null; 19     private ProgressBar firstBar=null; 20     private Toast toast=null; 21     @Override 22     protected void onCreate(Bundle savedInstanceState) { 23         super.onCreate(savedInstanceState); 24         setContentView(R.layout.main); 25          26         //根据ID获取对象 27         startButton =(Button)findViewById(R.id.startButton); 28         endButton=(Button)findViewById(R.id.endButton); 29         firstBar=(ProgressBar)findViewById(R.id.firstBar); 30         //给对象设置动作监听器 31         startButton.setOnClickListener(new StartButtonListener()); 32         endButton.setOnClickListener(new EndButtonListener()); 33     } 34  35     class StartButtonListener implements OnClickListener{ 36  37         @Override 38         public void onClick(View v) { 39             // TODO Auto-generated method stub 40             //一开始执行,加入到消息队列,不延迟, 41             //然后马上执行run方法 42             firstBar.setVisibility(View.VISIBLE); 43             firstBar.setMax(100); 44             handler.post(upRunnable); 45             toast=Toast.makeText(Handler_01.this, "运行开始", Toast.LENGTH_SHORT); 46             toast.setGravity(Gravity.CENTER, 0, 0); 47             toast.show(); 48         } 49     } 50     class EndButtonListener implements OnClickListener{ 51  52         @Override 53         public void onClick(View v) { 54             // TODO Auto-generated method stub 55             //停止 56             handler.removeCallbacks(upRunnable); 57             System.out.println("It's time to stop..."); 58         } 59     } 60      61     //创建handler对象,在调用post方法 62     //异步消息处理:将下载或者处理大数据等等单独放到另一个线程 63     //更好的用户体验 64     Handler handler=new Handler(){ 65          66         @Override 67         public void handleMessage(Message msg){ 68             firstBar.setProgress(msg.arg1); 69             firstBar.setSecondaryProgress(msg.arg1+10); 70             //handler.post(upRunnable); 71             if(msg.arg1<=100) {   72                 handler.post(upRunnable);    //将要执行的线程放入到队列当中     73             }else {   74                 handler.removeCallbacks(upRunnable);     75             }   76         } 77     }; 78      79     //声明线程类:实现Runnable的接口 80     Runnable upRunnable=new Runnable() { 81          82         int i=0; 83         @Override 84         public void run() {
//程序的运行状态 85 // TODO Auto-generated method stub 86 //postDelayed方法:把线程对象加入到消息队列中 87 // 隔2000ms(延迟) 88 System.out.println("It's time to start..."); 89 i=i+10; 90 //获取Message消息对象 91 Message msg=handler.obtainMessage(); 92 //将msg对象的arg1(还有arg2)对象的值设置 93 //使用这两个变量传递消息优点:系统消耗性能较少 94 msg.arg1=i; 95 try{ 96 //设置当前显示睡眠1秒 97 Thread.sleep(1000); 98 }catch(InterruptedException e){ 99 e.printStackTrace();100 }101 //将msg对象加入到消息队列当中102 handler.sendMessage(msg);103 if(i==100){
//当值满足时,将线程对象从handle中剔除104 handler.removeCallbacks(upRunnable);105 firstBar.setVisibility(View.GONE);106 //临时弹出107 108 toast=Toast.makeText(Handler_01.this, "运行结束", Toast.LENGTH_SHORT);109 toast.setGravity(Gravity.CENTER, 0, 0);110 toast.show();111 }112 }113 };114 }

main.xml

1 
7 8
14 15
20 21
26 27

 

总结:

    1)当点击开始或者运行结束的时候,都会通过调用Toas弹出临时窗口,Toast.makeText(Handler_01.this, "运行结束", Toast.LENGTH_SHORT),这一句一开始总是执行出错,原因在于必须调用它的show方法才可以显示出来,还可以通过设置它的位置来显示;

    2)在xml中  android:text="@string/end",则需要在layout下的string文件中敲写相应的代码

    3)原本代码有一些瑕疵,就是没有下面这一段代码:

1             if(msg.arg1<=100) {  2                 handler.post(upRunnable);    //将要执行的线程放入到队列当中    3             }else {  4                 handler.removeCallbacks(upRunnable);    5             }

   这样就导致了upRunnable的run方法出现了死循环,这样,虽然程序UI本身没有问题,但是内部却又很大的缺陷

  

   这是因为

1           if(i==100){
//当值满足时,将线程对象从handle中剔除2 handler.removeCallbacks(upRunnable);3 firstBar.setVisibility(View.GONE);4 toast=Toast.makeText(Handler_01.this, "运行结束", Toast.LENGTH_SHORT);5 toast.setGravity(Gravity.CENTER, 0, 0);6 toast.show();7 }

    这一段代码看似是把upRunnable线程从线程对象队列中移除,但是再次之前又前执行了handler.sendMessage(msg);这句代码

    从而导致下面的代码又被执行到

1         public void handleMessage(Message msg){2             firstBar.setProgress(msg.arg1);3             firstBar.setSecondaryProgress(msg.arg1+10);4             5         }

     这样肯定会使upRunnable线程重新加入到线程对象队列中,updateThread的run方法重复执行,这就导致了死循环。所以必须加上之前的那段代码,通过判断来控制循环终止。并且run方法中的if(i==100)的那段代码也是可以不用的,不过我是写了一些其他代码就懒得优化了,这是后话了。

     4)  刚刚大家看到我们可以通过敲写System.out.println在logcat中显示,一开始eclipse编译器中是没有,这是如何显示出来的?

   大家可以再window的show view中找到logCat(deprecated)通过下图中绿色的“+”添加出来

                      

然后显示内容的时候,选择右上角“V  D I W E ”的I就可以比较清晰的显示出来了,当然你也可以选择另外一个logCat来显示,方法类似。

    5)实际上,Handler在默认情况下,和调用它的Activity是处于同一个线程的。 上述Handler的使用示例中,虽然声明了线程对象,但是在实际调用当中它并没有调用线程的start()方法,而是直接调用当前线程的run()方法。

        如果要实现调用另一个新的线程,只要注释post方法,然后加上这样两段代码即可:  Thread t = new Thread(r);   t.start(); 

转载地址:http://zerml.baihongyu.com/

你可能感兴趣的文章
SQL 语法速成手册
查看>>
使用nginx控制ElasticSearch访问权限
查看>>
JVM必问知识点:类加载过程
查看>>
Markodwn 标题对齐的同步滚动
查看>>
Flutter 界面路由浅析
查看>>
终端学习记录
查看>>
Python3之递归函数简单示例
查看>>
docker命令使用记录
查看>>
Mybatis入门学习---使用注解开发
查看>>
W3C HTML测试答案
查看>>
ES6 Symbol 使用场景
查看>>
Vue递归组件实现树形结构菜单
查看>>
webpack4-css样式处理
查看>>
浅谈华为如何实现区块链的安全隐私保护
查看>>
深度解析 create-react-app 源码
查看>>
简述HTTPS原理
查看>>
小程序骨架屏动态注入组件
查看>>
Java 事务详解
查看>>
MySQL学习笔记——读《MySQL技术内幕 InnoDB存储引擎》
查看>>
关于新版chrome与火狐自动填充账号密码的问题
查看>>