您的位置:首页 > 移动开发 > Android开发

Android Handler,Loop,HandlerThread消息处理

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

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



上面图中的模型,就平时很常见的当需要更新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> : 新建一个Android工程:



<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两个的区别,哪一个会产生并线操作的问题,哪个才是真正合理的.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: