使用Thread+Handler或runOnUiThread更新UI

来源:互联网 发布:网络微营销 编辑:程序博客网 时间:2024/05/29 11:46
众所周知,在非主线程中更新UI会发生ANR,所以通常使用handler。
创建一个Handler类的实例,在这个Handler实例的handleMessage回调函数中调用更新界面显示的函数。

还有一种封装好的方法:runOnUiThread:点击按钮,更新UI。

把更新ui的代码创建在Runnable中,然后在需要更新ui时,把这个Runnable对象传给runOnUiThread(Runnable)。 这样Runnable对像就能在ui线程中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程。

其实和handler差不多,都是将这个更新UI的请求消息,加入到事件队列,等待主线程空闲的时候执行。

package code.xzy.com.updateuidemo;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.TextView;/** * 测试更新UI的两种方式 * 1.Handler:mHandler通过调用sendMessage()分发消息,交给handleMessage()处理 * 2.runOnUiThread: * 把更新ui的代码创建在Runnable中,然后在需要更新ui时, * 把这个Runnable对象传给runOnUiThread(Runnable)。 * 这样Runnable对像就能在ui程序中被调用。如果当前线程是UI线程, * 那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程。 */public class MainActivity extends Activity {    private TextView mTextView;    private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case 1:                    mTextView.setText("update UI by handler.");                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mTextView = (TextView) findViewById(R.id.info_tv);        findViewById(R.id.update_text_by_handler).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new Thread(new Runnable() {                    @Override                    public void run() {                        mHandler.sendEmptyMessage(1);                    }                }).start();            }        });        findViewById(R.id.update_text_by_runOnUiThread).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new Thread(new Runnable() {                    @Override                    public void run() {                        try {                            //模拟耗时操作                            Thread.sleep(5000);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                        //更新UI的代码                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                mTextView.setText("update UI by runOnUiThread.");                            }                        });                    }                }).start();            }        });    }}
补充:Andriod如何处理UI与耗时操作的通信,有哪些方式及各自的优缺点

主要有三种方法:
1.Handler

handler机制是,在主线程中创建handler对象, 当执行耗时操作时,新建一个线程,在这个线程中执行耗时操作,通过调用handler的sendMessage,post等方法,更新ui界面;
2.AsyncTask

AsyncTask本质上是一个线程池,所有的异步任务都会在这个线程池中的工作线程中执行,当需要操作ui界面时,会和工作线程通过handler传递消息;
3.自己开子线程执行耗时操作,然后调用Activity的runOnUiThread()方法更新ui; 

自己开子线程执行耗时操作,然后调用Activity的runOnUiThread()方法更新ui,这种方法需要把context对象强制转换成activity后使用 

各自优缺点:
 Handler机制的优点是  结构清晰,功能明确,但是代码过多;
 AsyncTask简单,快捷,但是可能会新开大量线程,消耗系统资源,造成FC; 
 runOnUiThread()方法最好用,代码也非常简单,只是需要传递context对象.