使用Thread+Handler或runOnUiThread更新UI

众所周知,在非主线程中更新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对象.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值