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

  • 相关阅读:
    [leetcode] Palindrome Number
    [leetcode] Find Minimum in Rotated Sorted Array
    [leetcode] Word Search
    [leetcode] Construct Binary Tree from Preorder and Inorder Traversal
    [leetcode] Flatten Binary Tree to Linked List
    [leetcode] Recover Binary Search Tree
    [leetcode] Unique Binary Search Trees II
    [leetcode summary] Dynamic Programming
    [leetcode] Generate Parentheses
    [leetcode summary] Backtracing
  • 原文地址:https://www.cnblogs.com/daomul/p/2909391.html
Copyright © 2011-2022 走看看