zoukankan      html  css  js  c++  java
  • Android 学习 笔记_02. handler的使用

         大家知道,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 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:orientation="vertical"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     tools:context=".Handler_01" >
     7 
     8     <ProgressBar 
     9         android:id="@+id/firstBar"
    10         style="?android:attr/progressBarStyleHorizontal"
    11         android:layout_width="200dp"
    12         android:layout_height="wrap_content"
    13         android:visibility="gone"/>
    14     
    15      <Button
    16          android:id="@+id/startButton"
    17         android:layout_width="wrap_content"
    18         android:layout_height="wrap_content"
    19         android:text="@string/start" />
    20      
    21      <Button
    22          android:id="@+id/endButton"
    23         android:layout_width="wrap_content"
    24         android:layout_height="wrap_content"
    25         android:text="@string/end" />
    26 
    27 </LinearLayout>

    总结:

        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(); 

  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/daomul/p/2909391.html
Copyright © 2011-2022 走看看