您的位置:首页 > 产品设计 > UI/UE

Android消息处理机制(Handler、Looper、MessageQueue与Message)

2015-03-26 13:49 591 查看
我们知道出于性能优化的考虑,Android的UI操作并不是线程安全的,这意味着多个线程并发操作UI组件,可能会导致线程安全的问题。因此,Android指定一条简单的规则,只允许UI线程操作Activity里面的UI组件。但是在实际的开发中,我们难免需要让新启动的线程周期性的改变界面组件的属性值,这就是需要Handler消息传递机制来实现。

Handle类的主要作用有两个:

1、在新启动的线程中发送消息;

2、在主线程中获取、处理消息。

为了让主线程能“适时”地处理新启动的线程所发送的消息,显然只能通过回调的方式来实现——开发者只要重写Handler类中处理消息的方法,当新启动的线程发送消息时,Handler类中处理消息的方法被自动回调。消息会发送到与之关联的MessageQueue,而Handler不断从MessageQueue中获取并处理消息——这将导致Handler类中的处理消息的方法被回调。

 

Handler中包含如下方法用于发送和处理消息。

voidhandleMessage(Message msg):处理消息的方法。该方法通常用于被重写。

final booleanhasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。

final booleanhasMessage(int what,Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息。

多个重载的Message(int what):获取消息。

sendEmptyMessage(intwhat):发送空消息。

final boolean sendEmptyMessageDelayed(intwhat,long delayMillis):指定多少毫秒之后发送空消息。

final booleansendMessage(Message msg):立即发送消息。

通过这些方法,程序就可以方便的利用Handler来进行消息传递了。

 

Android是消息驱动的,实现消息驱动有几个要素:

    消息的表示:Message。Handler接收和处理的消息对象

    消息队列:MessageQueue消息队列,他是采用先进先出的方式来进行管理Message。程序创建Looper对象时,会在他的构造其中创建MessageQueue对象,

消息循环,用于循环取出消息进行处理:Looper。每个线程只能拥有一个Looper对象。他的Looper方法负责读取MessageQueue中的消息。读到信息之后就把消息交给发送该消息的Handler进行处理。

所以MessageQueue是由Looper对象负责管理的,也就是说希望Handler正常工作,在当前的线程中必须有一个Looper对象。为了保证当前线程中有一个Looper对象可以分为以下两种情况考虑:

1、主UI线程线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可以通过Handler发送和处理消息。

2、程序员主动启动的子线程,这个程序员必须自己创建一个Looper对象,并且启动他。创建Looper对象调用他的prepare()方法即可。

消息处理,消息循环从消息队列中取出消息后要对消息进行处理:Handler。Handler的作用有两个——发送和处理消息。程序使用Handler发送消息。被Handler发送的消息必须被送到指定的MessageQueue。接收消息是指Handler接收Loop处理完之后发送给他的消息。

看一下,下面的图片一定程度上解释了Android的消息处理机制。


下面我们来看一段代码。很好的解释了Handler和Looper的使用:

public class MainActivity extends Activity implements OnClickListener {
private static final String UPPER_NUM = "upper_num";
private static final String RESULTE_NUM = "result_num";
protected static final int RESULTE = 0;
EditText getEditText;
Button calButton;
TextView resultTextView;
CalThread calThread;

Handler mainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case RESULTE:
String result = msg.getData().getString(RESULTE_NUM);
Log.i("mainHandler", "result=="+result);
resultTextView.setText(result);
break;
default:
break;
}
}

};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
calThread = new CalThread();
// 启动新线程
calThread.start();
initView();
callBackListener();
}

private void initView() {
getEditText = (EditText) findViewById(R.id.editText1);
calButton = (Button) findViewById(R.id.button1);
resultTextView = (TextView) findViewById(R.id.textView3);
}

private void callBackListener() {
calButton.setOnClickListener(this);
}

/**
* <功能描述>质数计算子线程
*/
class CalThread extends Thread {
private Handler mHandler;

@Override
public void run() {
Log.i("run", "run");
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
int upper = msg.getData().getInt(UPPER_NUM);
// 父类接口指向子类对象的引用
List<Integer> nums = new ArrayList<Integer>();
// 从2开始计算所有的质数
outer: for (int i = 2; i <= upper; i++) {
// 用i除以2开始、到i的平方根的所有数
for (int j = 2; j <= Math.sqrt(i); j++) {
// 如果可以整除,则表明这个数不是质数
if (i != 2 && i % j == 0) {
continue outer;
}
}
nums.add(i);
}
Toast.makeText(MainActivity.this, nums.toString(), Toast.LENGTH_LONG).show();
Message msgMessage = new Message();
msgMessage.what = RESULTE;
Bundle bundle = new Bundle();
bundle.putString(RESULTE_NUM, nums.toString());
msgMessage.setData(bundle);
// 向主线程中的Handler中发送消息
mainHandler.sendMessage(msgMessage);
}
}

};
Looper.loop();
}

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

@Override
public void onClick(View v) {
Log.d("Click", "Click");
cal();

}

private void cal() {
Message msgMessage = new Message();
msgMessage.what = 0x123;
Bundle bundle = new Bundle();
bundle.putInt(UPPER_NUM, Integer.parseInt(getEditText.getText().toString()));
msgMessage.setData(bundle);
// 向新线程中的Handler中发送消息
calThread.mHandler.sendMessage(msgMessage);
}

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