android handler looper 实例,Android的Handler Looper Message机制应用实例与详解(一)

Android的UI操作不是线程安全的(出于提高性能考虑,避免实现多线程同步等机制所引入的延时),若多个线程同时对UI元素进行操作,可能导致线程安全问题。因此,Android中做了严格的规定:只有UI主线程才能对UI进行设置与操作。

在实际编程中,为了避免UI界面长时间得不到响应而导致的ANR(Application Not Responding)异常,通常将网络访问、复杂运算等一些耗时的操作被放在子线程中执行。这就需要子线程在运行完毕后将结果返回到主线程并通过UI进行显示。在Android中,是通过Handler+Loop+MessageQueue实现线程间通信的。

先看两个实例:

实例1:模拟通过网络下载数据并返回UI显示。

操作过程为:1.UI线程获得用户请求。2.启动子线程完成网络数据下载(网络下载过程通过强制子线程休眠若干秒来模拟)。3.子线程将下载的数据返回UI线程并显示。

主要代码如下:public class MainActivity extends ActionBarActivity {

private Button mButton;

private TextView mTextView;

private Handler mHandler;

private Thread mNetAccessThread;

private ProgressDialog mProgressDialog;

private int mDownloadCount = 0;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.fragment_main);

mButton = (Button) findViewById(R.id.btReqNet);

mTextView = (TextView) findViewById(R.id.tvDownload);

//设置按钮的点击事件监听器

mButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

showProgressDialog("","正在下载...");

//启动子线程进行网络访问模拟

mNetAccessThread = new ChildTread();

mNetAccessThread.start();

}

});

//继承Handler类并覆盖其handleMessage方法

mHandler = new Handler(){

//覆盖Handler类的handleMessage方法

//接收子线程传递的数据并在UI显示

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case 1:

mTextView.setText((String) msg.obj);

dismissProgressDialog();

break;

//可以添加其他情况,如网络传输错误

//case...

default:

break;

}

}

};

}

class ChildTread extends Thread {

@Override

public void run() {

//休眠6秒,模拟网络访问延迟

try {

Thread.sleep(6000);

} catch (InterruptedException e) {

e.printStackTrace();

}

//将结果通过消息返回主线程

Message msg = new Message();

msg.what = 1;

mDownloadCount ++;

msg.obj = new String("第"+mDownloadCount+"次从网上下载的数据");

mHandler.sendMessage(msg);

}

};

/**

* 开启progressDialog.

*

* @param title 对话框标题.

* @param content 对话框正文.

*/

protected void showProgressDialog(String title,String content) {

mProgressDialog = new ProgressDialog(this);

if(title != null)

mProgressDialog.setTitle(title);

if(content != null)

mProgressDialog.setMessage(content);

mProgressDialog.show();

}

/**

* 关闭progressDialog.

*

*/

protected void dismissProgressDialog() {

if(mProgressDialog != null)

{

mProgressDialog.dismiss();

}

}

}

程序运行效果:

点击下载按钮,UI线程通过handler.sendMessage()向子线程发送消息,子线程收到消息后启动数据下载(通过休眠线程模拟)。

f8d739b3d7409f5fd16419d28adcdbea.png

下载完毕,子线程将下载数据返回主线程并显示。

58721be513df9fb1e1d83acbaf5cf816.png

实例2:模拟子线程向主线程发送消息。

操作过程为:1.UI线程获得用户输入的消息内容。2.通过Handler将消息发送给子线程。3.子线程获得消息并通过Toast将内容打印。

主要代码如下:public class MainActivity extends ActionBarActivity {

private EditText mEditText;

private Button mButton;

private Handler mHandler;

private Thread mChildTread;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.fragment_main);

mEditText = (EditText) findViewById(R.id.etEditText);

mButton = (Button) findViewById(R.id.btButton);

// 设置按钮的点击事件监听器

mButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Message msg = new Message();

msg.what = 1;

msg.obj = mEditText.getText();

//将消息发送到子线程

mHandler.sendMessage(msg);

mEditText.setText("");

}

});

//启动子线程进行msg接收

mChildTread = new ChildTread();

mChildTread.start();

}

/**

* 子线程为内部类,可以直接访问其外部类的mHandler变量

*

*/

class ChildTread extends Thread {

@Override

public void run() {

//以下三步是handler looper机制工作的固定模式

Looper.prepare();

mHandler = new Handler() {

public void handleMessage(Message msg) {

// process incoming messages here

switch (msg.what) {

case 1:

//子线程无权操作UI,只能通过Toast.makeText将收到的消息显示

String st = msg.obj.toString();

if (st == null || st.equals(""))

st = "收到的消息内容为空";

else

st = "收到来自主线程的消息:" + st;

Toast.makeText(MainActivity.this, st, 6000).show();

break;

//可以添加其他情况,如传输错误

//case...

default:

break;

}

}

};

Looper.loop();

}

};

}

程序运行效果:

51325481ed95f68db302482ffb946cfd.png3c82e81778a26ba0131b3b0550913a92.png

小结:Android通过Handler+Looper+MessageQueue机制实现线程间的通信,本文通过两个简单的实例分别基于该机制实现了UI线程到子线程和子线程到UI线程的消息传递。下一篇博文将会对Handler Looper机制的原理进行深入研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值