Android Handler,Loop,HandlerThread消息处理
博客标题也不知道写什么好,仅仅是近期有时候发现Handler,Loop,HandlerThread非常easy混淆,所以做了简单的笔记处理:
第一种 : 大概的意思给出说明图:
上面图中的模型,就平时非经常见的当须要更新UI时,通过Handler发送一个Message事件出去,可是Message事件的路径是先入了主线程的MessageQueue队列(通常是FIFO模式)中,
然后Looper就像一个永恒的发动机一样,不断的"循环"的去查询MessageQueue队列中是否有Message消息,假设查询存在,就会然其出队列来处理,因为这个消息队列是共用主线程中的(这句话非常重要)MessageQueue,所以它能够更新UI显示或者做一些其它的事情,主要还是更新UI较多(在主线程中).
另外一种:以下这一种事实上更具有普遍性
为什么说更具有普遍性,事实上能够想一想Activity事实上也相当于一个线程对象/或者封装了线程对象,我看了mMainThread等里面的消息循环,大致这么理解的.将理论非常难理解,
比方说,开发人员要向一个对象依次按顺序发送N个消息,第N-a个消息不能够在N-a-1个消息未运行完毕就開始,即保证前面一个消息运行完毕了,才干够运行下一个消息,平时开发中这种情况非经常见,可是要注意,假设我们在Activity中新建一个Thread线程,那就相当于独立于主线程之外,所以在这个线程中不能够处理更新UI等事情,可是却能够做非常多其它逻辑处理,并且它不会影响主线程的,它仅仅会在它自己的线程中按着顺序一个一个的运行.
第三种: 另一个HandlerThread,看了非常多例子,既然在Thread单词前面加上Handler,就和Handler扯上了关系,可是这个我自己还须要研究研究它正真的机制,仅仅知道这个东西新建以后,让其start,开发人员做一些更新UI或者其它事情,系统会安排在后台"慢慢"的帮开发人员完毕,即使事情里面加了延时也不用当心,他不会去堵塞主线程的.
以下给出一个測试程序验证一下:
<1> : 新建一个Androidproject:
<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两个的差别,哪一个会产生并线操作的问题,哪个才是真正合理的.
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号