android学习之Handler兑现异步与多线程

android学习之Handler实现异步与多线程

简而言之一些比较耗时的操作不要在主线程中等待,而是实现异步加载,比如那些下载的操作,如果文件小,网速快,可能一下也完了。。要是文件大了,网速不给力,势必拖垮主线程,用户体验也差。于是android中使用handler来处理这些事情。

xml中定义两个button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    
    <Button  
        android:id="@+id/start"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:text="@string/start"
    />
    <Button  
        android:id="@+id/stop"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:text="@string/stop"
    />

</LinearLayout>

android学习之Handler兑现异步与多线程

HanderActivity.java继承自Activity.java

package com.myandroid.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class HanderActivity extends Activity {
    /** Called when the activity is first created. */
        Button startButton = null;
        Button endButton = null;
        Handler handler = new Handler();
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            startButton = (Button)findViewById(R.id.start);
            startButton.setOnClickListener(new StartListener());
            endButton = (Button)findViewById(R.id.stop);
            endButton.setOnClickListener(new EndListener());
            System.out.println(Thread.currentThread());
        }
         
        class StartListener implements OnClickListener{
     
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                handler.post(HandlerThread);
            }
             
        }
         
        class EndListener implements OnClickListener{
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                handler.removeCallbacks(HandlerThread);
            }
             
        }
        

//匿名内部类一个线程
        Runnable HandlerThread = new Runnable() {
             
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("HandlerThread is Running......");
                System.out.println(Thread.currentThread());
                handler.postDelayed(HandlerThread, 3000);
            }
        };
}

①,当start按钮按下的时候,handler会通过执行代码handler.post(HandlerThread)把HandlerThread线程加入到handler的线程队列中,执行线程的run()方法,

②,在run()方法中,handler.postDelayed(HandlerThread, 3000)再次将线程放入handler队列,设置延时3000ms,这样是整个线程每个3000ms打印出:HandlerThread is Running......

③但是,在这里其实还是在一个线程里面,通过 System.out.println(Thread.currentThread())的输出结果可以看出都是主线程
android学习之Handler兑现异步与多线程

2,要实现handler异步的

1,Message类


每个消息都有一个队列,队列中存放的就是Message对象,obtainMessage()来获得消息对象。同时,Message对象是用来传递使用的,它能传递两个整型和一个Object,尽量使用Message的arg1与arg2两个整型来传递参数,那样系统消耗最小(API如是说),如果传递数据量比较大,则可以使用setData(Bundle a)的方法,其中的Bundle对象可以粗略的看成是一个Map对象,但它的Key都是String,而value是有限的一些类型,可以再API里查看。

2,Looper类

Looper能够循环滴从消息队列中取得消息,一般通过thread的getLooper()方法获得一个Looper对象

package com.myandroid.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 MessageLooperHandler extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        System.out.println("Activity---->"+Thread.currentThread().getName());
      //创建一个HandlerThread对象,它是一个线程
        HandlerThread handlerThread = new HandlerThread("HandlerThread");
      //启动线程
        handlerThread.start();
      //创建一个MyHandler对象,该对象继承了Handler,从下面的MyHandler类中可以看到,
      //调用的是Handler父类的Handler(Looper looper)的构造函数,而这里传进去的Looper对象是从HandlerThread中取得的。
        MyHandler myHandler = new MyHandler(handlerThread.getLooper());
      //获得消息对象
        Message msg = myHandler.obtainMessage();
      //把得到的消息对象发送给生成该消息的Handler,即myHandler,
      //当myHandler接收到消息后,就会调用其handleMessage的方法来处理消息
        msg.sendToTarget();
    }
     
    class MyHandler extends Handler{
        public MyHandler() {//构造函数
            // TODO Auto-generated constructor stub
        }
         
        public MyHandler(Looper looper){//构造函数
            super(looper);//实现了父类的该构造函数
        }
         
      //当这个Handler接收到Message对象的时候,会自动调用这个方法,来对Message对象进行处理
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            System.out.println("Handler---->"+Thread.currentThread().getName());
        }
    }
}

这时运行MessageLooperHandler这个Activity可以看到:是两个线程了

android学习之Handler兑现异步与多线程

实现与主线程的分离,从而可以实现多线程和异步处理。