Android Handler,Loop,HandlerThread消息处理

博客标题也不知道写什么好,只是最近有时候发现Handler,Loop,HandlerThread很容易混淆,所以做了简单的笔记处理:

第一种 : 大概的意思给出说明图:

Android Handler,Loop,HandlerThread消息处理_第1张图片

上面图中的模型,就平时很常见的当需要更新UI时,通过Handler发送一个Message事件出去,但是Message事件的路径是先入了主线程的MessageQueue队列(一般是FIFO模式)中,

然后Looper就像一个永恒的发动机一样,不断的"循环"的去查询MessageQueue队列中是否有Message消息,如果查询存在,就会然其出队列来处理,由于这个消息队列是共用主线程中的(这句话非常重要)MessageQueue,所以它可以更新UI显示或者做一些其他的事情,主要还是更新UI较多(在主线程中).


第二种:下面这一种其实更具有普遍性

Android Handler,Loop,HandlerThread消息处理_第2张图片

为什么说更具有普遍性,其实可以想一想Activity其实也相当于一个线程对象/或者封装了线程对象,我看了mMainThread等里面的消息循环,大致这么理解的.将理论很难理解,

比如说,开发者要向一个对象依次按顺序发送N个消息,第N-a个消息不能够在N-a-1个消息未执行完成就开始,即保证前面一个消息执行完成了,才能够执行下一个消息,平时开发中这样的情况很常见,但是要注意,如果我们在Activity中新建一个Thread线程,那就相当于独立于主线程之外,所以在这个线程中不能够处理更新UI等事情,但是却可以做很多其他逻辑处理,而且它不会影响主线程的,它只会在它自己的线程中按着顺序一个一个的执行.


第三种: 还有一个HandlerThread,看了很多样例,既然在Thread单词前面加上Handler,就和Handler扯上了关系,但是这个我自己还需要研究研究它正真的机制,只知道这个东西新建以后,让其start,开发者做一些更新UI或者其他事情,系统会安排在后台"慢慢"的帮开发者完成,即使事情里面加了延时也不用当心,他不会去阻塞主线程的.


下面给出一个测试程序验证一下:

<1> : 新建一个Android工程:

Android Handler,Loop,HandlerThread消息处理_第3张图片


<2> : DurianMainActivity.java

package com.durian.handlerthread;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class DurianMainActivity extends Activity {

    private final static String TAG = "DurianMainActivity";
    private TextView mTextView;
    private TextView mTextViewA;
    private TextView mTextViewB;
    private TextView mTextViewC;

    private Button mButton;
    private Button mButtonA;
    private Button mButtonB;
    private Button mButtonC;

    private HandlerThread mHandlerThread;
    private HandlerThread mHandlerThreadA;

    private Handler mUIHandler;
    private Handler mUIHandlerA = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);

            mNumCount++;
            mTextViewA.setText("mNumCount : " + mNumCount);

        }

    };
    
    private Handler mUIHandlerB=new Handler(){

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            mTextViewB.setText("Number : "+mNumber++);  
            
            Log.i(TAG,"Number : "+mNumber);
            
        }
        
    };
    
    private int mLooperNum=0;
    
    private class LooperThread extends Thread{

        public Handler mLooperHandler;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            Looper.prepare();
            mLooperHandler=new Handler(){

                @Override
                public void handleMessage(Message msg) {
                    // TODO Auto-generated method stub
                    super.handleMessage(msg);

                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    
                    Log.i(TAG,"mLooperNum : "+mLooperNum++);
                    //here is not UI thread
//                    mTextViewC.setText("mLooperNum : "+mLooperNum);
                    
                }
                
            };
            
            Looper.loop();
            
        }

    }
    
    private LooperThread mLooperThread;

    private Handler mBackgroundHandler;
    private Handler mBackgroundHandlerA;

    private int mCount = 0;
    private int mNumCount = 0;
    private int mNumber=0;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.durian_main);

        mTextView = (TextView) findViewById(R.id.durianview);
        mTextView.setText("ui count : " + mCount);

        mTextViewA = (TextView) findViewById(R.id.durianaview);
        
        mTextViewB = (TextView) findViewById(R.id.durianbview);
        
        mTextViewC=(TextView)findViewById(R.id.duriancview);
        
        mLooperThread=new LooperThread();
        mLooperThread.start();
        
        mButtonC=(Button)findViewById(R.id.buttonC);
        mButtonC.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Message msg=new Message();
                msg.what=1;
                mLooperThread.mLooperHandler.sendMessage(msg);
                                
            }
            
        });
        
        mButtonB=(Button)findViewById(R.id.buttonB);
        mButtonB.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new Thread(){

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        super.run();
                        Looper.prepare();
                        
                        Message msg=new Message();
                        msg.what=100;
                        mUIHandlerB.sendMessage(msg);
                        
                        Looper.loop();
                        
                    }
                    
                }.start();
            }
            
        });

        mButtonA = (Button) findViewById(R.id.buttonA);
        mButtonA.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                mBackgroundHandlerA.post(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Message msg = new Message();
                        msg.what = 100;
                        mUIHandlerA.sendMessage(msg);

                    }

                });

            }

        });

        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                mBackgroundHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub

                        for (int i = 0; i < 1; i++) {

                            mUIHandler.post(new Runnable() {

                                @Override
                                public void run() {
                                    // TODO Auto-generated method stub
                                    mCount++;
                                    try {
                                        Thread.sleep(500);
                                    } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                    mTextView.setText("ui count : " + mCount);
                                    Log.i(TAG, "ui count : " + mCount);

                                }

                            });

                        }

                    }

                });

            }

        });

        mHandlerThread = new HandlerThread("backgroun_thread_post");
        mHandlerThread.start();

        mHandlerThreadA = new HandlerThread("backgroun_thread_send");
        mHandlerThreadA.start();

        mBackgroundHandler = new Handler(mHandlerThread.getLooper());

        mBackgroundHandlerA = new Handler(mHandlerThreadA.getLooper());

        mUIHandler = new Handler();

    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();

        mHandlerThread.getLooper().quit();

    }

}

durian_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".DurianMainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/durianview"
        android:text="@string/hello_world" />
    
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start"
        android:id="@+id/button"/>
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/durianaview"
        android:text="@string/hello_world" />
    
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="startA"
        android:id="@+id/buttonA"/>
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/durianbview"
        android:text="@string/hello_world" />
    
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="startB"
        android:id="@+id/buttonB"/>
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/duriancview"
        android:text="@string/hello_world" />
    
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="startC"
        android:id="@+id/buttonC"/>

</LinearLayout>

程序很简答,运行点击对应的按钮,就可以测试上面的结论了.

另外看一下按钮StartB和StartC两个的区别,哪一个会产生并线操作的问题,哪个才是真正合理的.
















你可能感兴趣的:(Android Handler,Loop,HandlerThread消息处理)