文档章节

handler的讲解

m
 m_ky
发布于 2015/05/14 22:43
字数 2433
阅读 132
收藏 0
package com.example.handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends ActionBarActivity {
 private Button startButton, endButton, button;
 private Handler handler;
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
         
   @Override
   public void onClick(View v) {
    handler.post(runnable);   //把这个线程放进runnable消息队列中处理
   }
  });
    
        findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    handler.removeCallbacks(runnable);  //删除这个线程
   }
  });  
        
    }
    Runnable runnable = new Runnable() {
  
  @Override
  public void run() {
   System.out.println("runnable");
   handler.postDelayed(runnable, 3000); //3秒之后,再把runnabl线程放入消息队列中去
   
  }
 };
}

handle类使用的步骤:
1.new个handle类。 

Handler handler = new Handler();   //每个handler都有与之关联的消息队列

2.实现线程对象,重写run方法,一般的很多数据处理都是由run方法来进行的。通过匿名类来new接口

Runnable updataThread = new Runnable() {

@Override
public void run() {
System.out.println("UpdataThread");
handler.postDelayed(updataThread, 3000);
}
};

3.添加到消息队列中去,一般都是监听的方法中去实现。

handler.post(updataThread);

4.删除线程
handler.removeCallbacks(updataThread);

什么是异步的消息处理机制呢?

handler.post(runnable);把线程放到消息队列中去,就返回了。剩下的工作就由:

System.out.println("runnable");
handler.postDelayed(runnable, 3000);来进行操作了。

mars老师的代码,用来做笔记。

 package mars.barhandler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
public class TestBarHandler extends Activity {
    /** Called when the activity is first created. */
 //声明控件变量
 ProgressBar bar = null;
 Button startButton = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //根据控件的ID得到代表控件的对象,并为按钮设置监听器
        
        bar = (ProgressBar)findViewById(R.id.bar);
        startButton = (Button)findViewById(R.id.startButton);
        startButton.setOnClickListener(new ButtonListener());
    }
    //当点击startButton按钮时,就会执行ButtonListener的onClick方法
    
class ButtonListener implements OnClickListener{
  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub
   bar.setVisibility(View.VISIBLE);
   updateBarHandler.post(updateThread);
  }
     
    }
    //使用匿名内部类来复写Handler当中的handleMessage方法
  Handler updateBarHandler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
   bar.setProgress(msg.arg1);
   Bundle bundle = msg.getData();
   updateBarHandler.post(updateThread); //把线程放到消息队列中去
   System.out.println("test---->" + bundle.getString("test"));
  }
     
    };
    //线程类,该类使用匿名内部类的方式进行声明
  Runnable updateThread = new Runnable(){
     int i = 0 ;
  @Override
  public void run() {
   System.out.println("Begin Thread" + i);
   i = i + 10 ;
   //得到一个消息对象,Message类是有Android操作系统提供
   
   Message msg = updateBarHandler.obtainMessage();

   //将msg对象的arg1参数的值设置为i,用arg1和arg2这两个成员变量传递消息,优点是系统性能消耗较少
   msg.arg1 = i ;
   Bundle bundle = new Bundle();
   bundle.putString("test", "test bundle");
   msg.setData(bundle);
   try {
    //设置当前显示睡眠1秒
    
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   //将msg对象加入到消息队列当中
   if( i > 100){
    //如果当i的值为100时,就将线程对象从handler当中移除
    updateBarHandler.removeCallbacks(updateThread);
    System.out.println(">>>>>>");
   }else{
    updateBarHandler.sendMessage(msg); //这里发生出的消息是由在定义的是的重新的handleMessage来进行处理 
    System.out.println("<<<<<<");
   }
  }
    };
    class MyThread extends Thread{
     public void run(){    
     }
    }

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<ProgressBar
 android:id="@+id/bar"
 style="?android:attr/progressBarStyleHorizontal"
 android:layout_width="200dp"
 android:layout_height="wrap_content"
 android:visibility="gone"
 />
<Button 
 android:id="@+id/startButton"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="start"/>
</LinearLayout>

讲解:

Message andriod系统提供的类。由于handler.post(updataThread);放入消息队列中的信息包含的是线程的对象(updateBarHandler.post(updateThread);)和对象内容(发送的数据 updateBarHandler.sendMessage(msg);),因此有两个消息队列。

基本思路:定义一个Handler并重写handleMessage方法,这里方法是用接收信息的。当调用到updateBarHandler.sendMessage(msg);那么系统就回调用重写后的handleMessage方法。 

handler.post(updataThread);handler.sendMessage(msgMessage);的区别?

handler.post(updataThread);是把线程压到消息队列中去,handler.sendMessage(msgMessage)是把消息压到消息队列中去。 

当消息压入消息进队列后,senMessage立即返回,这个消息不一定被执行。而是handleMessage,就从队列中取得消息进行处理。 因此说是发送消息和处理消息不是同步执行,称为消息的异步处理机制。

handler的作用是压入线程,压入消息到消息队列中去。

压入线程后,线程中压入消息。一般情况消息中又调用线程继续压入消息。

获得消息的方法:

handler.obtainMessage()是获得消息对象,消息对象由Android的系统提供 message

message中有arg1 arg2是传递消息,优点是节省性能。先是获得消息对象,再通过handler对象发生消息。

把线程放入消息队列中,那么同时也会把消息对象也放入了消息队列中。再通过handler用匿名内部类重写handlerMessage来接收,消息队列中的消息。

Handler与线程的关系?

上面的程序中,并没有调用到了Thread的start方法。这里说明Handler这个线程是跟UI线程(Android的主线程)是属于同一个线程的。

Bundle对象的讲解:

其实就是类似于map对象一样使用,但是它的键固定为String,值为多种类型。

 

其实handler跟UI线程是同一个线程,当处理的数据多起来的时候,就会出现很多问题,比如处理速度慢。

那么为了解决这个问题,就要用到looper了。looper的作用是从线程中取出消息,当消息队列中有消息就取出来,如果没有消息的时候就进入休眠状态。

那么就要使用到一个类,叫做HandlerThread,这里类里面封装了looper循环处理消息的功能。这个类由Android系统框架提供。

以下是复制其他人博客的:http://blog.sina.com.cn/s/blog_5da93c8f0101kio1.html

Handler会关联一个单独的线程和消息队列。Handler默认关联主线程,虽然要提供Runnable参数 ,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用HandlerThread。

HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,主要的作用是建立了一个线程,并且创立了消息队列,有来自己的looper,可以让我们在自己的线程中分发和处理消息。

package mars.handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
public class HandlerTest2 extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  //打印了当前线程的ID
  System.out.println("Activity-->" + Thread.currentThread().getId());
  //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由Android应用程序框架提供
  HandlerThread handlerThread = new HandlerThread("handler_thread");
  //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start(); 为了获取looper,就要生成HandlerThread对象
  handlerThread.start();
  MyHandler myHandler = new MyHandler(handlerThread.getLooper());
  Message msg = myHandler.obtainMessage();
  //将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象,这里的是myHandler对象
  Bundle b = new Bundle();
  b.putInt("age", 20);
  b.putString("name", "Jhon");
  msg.setData(b);
  msg.sendToTarget(); 
 }
 
 class MyHandler extends Handler{
  public MyHandler(){
   
  }
  public MyHandler(Looper looper){ //传递的looper进行绑定
   super(looper);
  }
  @Override
  public void handleMessage(Message msg) {
   Bundle b = msg.getData();
   int age = b.getInt("age");
   String name = b.getString("name");
   System.out.println("age is " + age + ", name is" + name);
   System.out.println("Handler--->" + Thread.currentThread().getId());
   System.out.println("handlerMessage");
  }
 }
}

 

HandlerThread继承自Thread,当线程开启时,也就是它run方法运行起来后,

线程同时创建了一个含有消息队列的Looper,并对外提供自己这个Looper对象的get方法,这就是它和普通Thread唯一不同的地方。当looper传递给了哪个对象,那么就可以使用looper进行消息队列的消息循环处理了。处理机制是:HandlerThread启动了一个新的线程,然后创建了一个含有消息队列的Looper来进行处理消息,那么这个Looper是绑定了一个Handler对象让来处理的。意思就是说HandlerThread开辟了一个新的线程,通过looper循环对象,把handle消息循环给HandlerThread进行处理,处理过程中如果handle的消息为空,那么looper就进入休眠状态了。

 

下面的是慕课网的handler讲解使用之一:

 通过handler放入消息队列中的Runnable对象来更新UI。注意:这里并没有开启新的线程,默认的时跟主线程绑定在一起的。

第一种更新UI的使用:

package com.example.handler02;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
 private TextView textView;
 Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.tv1);
        
        new Thread(){
         public void run() {
          
          try {
     Thread.sleep(1000);
     handler.post(new Runnable() {
      
      @Override
      public void run() {
       textView.setText("你好");
      }
     });
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
         };
        };
        
    }
  
}

第二种更新UI的使用:

 package com.example.handler02;
import android.support.v7.app.ActionBarActivity;
import android.R.integer;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
 
 
 private int image[] = {R.drawable.gl_switch_a_normal, R.drawable.gl_switch_b_normal,R.drawable.gl_switch_c_normal};
 private int index;
 private ImageView imageView;
 Handler handler = new Handler();
 Myrunnable myrunnable = new Myrunnable();
 
 class Myrunnable implements Runnable{
  @Override
  public void run() {
   index ++;
   index = index % 3; //重复循环
   imageView.setImageResource(image[index]);
   handler.postDelayed(myrunnable, 1000);
  }
 }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.imageView1);
        handler.postDelayed(myrunnable, 1000);
    }
  
}

 慕课网使用之二:

发送消息的使用第一种:这里启用了新线程进行发送消息。

 package cn.jamen.myhandler01;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
 
 private TextView textView;
 Handler handler = new Handler(){
  public void handleMessage(android.os.Message msg) {
   textView.setText(""+msg.arg1);
    textView.setText(""+msg.arg2);
  };
 };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.tv1);
        
        new Thread(){
         public void run() {
          try {
     Thread.sleep(3000);
     Message msg = new Message();
           msg.arg1 = 100;
           msg.arg2 = 88;
           handler.sendMessage(msg);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
         
         };
        }.start();
    }
}

 消息发送是由 handler.sendMessage(msg);发送出去,由系统回调handleMessag方法进行接受并出来。

这里就有两个线程,一个是主(UI)线程跟新开启的线程。以后不再使用handler.setMessage(msg)方法发送消息,而是使用msg.setData(bundle)设置消息,然后使用发送消息方法msg.sendToTarget(); 这里的发送方法的实现是调用msg与之关联的handler.sendMessage(msg)来发送消息的。 Message msg = updateBarHandler.obtainMessage(); 以后都是使用这个方法来获取Message对象,是由系统提供,效率高。

© 著作权归作者所有

m
粉丝 0
博文 1
码字总数 2433
作品 0
湛江
私信 提问
这是一份全面 & 详细的Android多线程知识总结指南

前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 今天,我将献上一份全面 & 详细的Android多线程学习指南,希望你们喜欢。 目录 1. 多线程基础知识 在了解Android多线程实现...

Carson_Ho
06/26
0
0
Android--多线程之Looper

转载自:https://www.cnblogs.com/plokmju/p/androidLooper.html 前言   上一篇博客讲解了Handler实现线程间通信,这篇博客讲解一下Handler运行的原理,其中涉及到MessageQueue、Looper。简...

犀牛有脾气
2018/12/06
0
0
Android:关于多线程的总结知识都在这里了!

前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 今天,我将献上一份全面 & 详细的Android多线程学习指南,希望你们喜欢。 目录

Carson_Ho
05/22
0
0
04-dbutils源码之 各种ResultSetHandler实现类

今天主要讲解下常用的Handler,Handler讲完之后,就能对dbutils整体有了了解了。 来看下ResultSetHandler接口 /** Implementations of this interface convert ResultSets into other object...

mnisummer
2013/09/26
1K
0
MQTT---HiveMQ源码详解(六)Netty-Handlers总览

源博客地址:http://blog.csdn.net/pipinet123 MQTT交流群:221405150 由于HiveMQ是基于netty做网络通讯层的框架,那么必定需要使用Handler来处理客户端的消息,那么HiveMQ的Handler主要分为七...

pipinet123
2017/03/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

设计模式之访问者模式

定义 Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which......

陈年之后是青葱
昨天
10
0
PhotoShop 高级应用 : 分层云彩 - 简单闪电效果

1.创建黑白渐水平渐变图层 2.选择滤镜选项卡: 渲染--->分层云彩功能 3.将滤镜-云彩效果渲染后的图层进行反相操作 【此时出现闪电效果】 6.调整色阶,使得闪电效果更明显 7.创建剪贴蒙版:色...

东方墨天
昨天
11
0
三种实现Android主界面Tab的方式

三种实现Android主界面Tab的方式 https://www.cnblogs.com/caobotao/p/5103673.html

shzwork
昨天
11
0
java8-Optional类

背景 NPE问题,100%的Java程序员都碰到,并且曾经是心中的痛。 1965年英国TonyHoare引入了Null引用,后续的设计语言包括Java都保持了这种设计。 一个例子 业务模型 Person 有车一族, 有Car...

春天springcarter
昨天
11
0
py 登录github时token以及cookie的应用

import requestsfrom bs4 import BeautifulSoup## 获取tokenr1 = requests.get('https://github.com/login')s1 = BeautifulSoup(r1.text,'html.parser')token = s1.find(name='input',......

子枫Eric
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部