实现RunOnUiThread和RunOnUiThreadBlock

现在需要实现一个工具类,RunUtils,这个类中包含runOnUiThread(Context context, Runnable runnable)和runOnUiThreadBlock(Context context, Runnable runnable)两个方法。两个方法都使runnable在UI线程执行,runOnUiThread立即返回,runOnUiThreadBlock等待runnable执行完毕后才返回。

根据context创建一个Handler,这个Handler用于发送消息。runOnUiThread这个方法不需要同步,runOnUiThreadBlock需要同步。

RunUtils内容

package com.letv.handlertest;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.lang.ref.WeakReference;

public class RunUtils {

    private static final int WHAT_BLOCK = 0x1001;

    private static WeakReference<Context> weakContext;
    private static WeakReference<Handler> weakHandler;
    private static Object lock = new Object();

    private static void init(Context context){
        if(RunUtils.weakContext == null ||
                (RunUtils.weakContext!=null && RunUtils.weakContext.get()!=context) ){
            RunUtils.weakContext = new WeakReference<Context>(context);

            Handler handler = new Handler(context.getMainLooper()) {
                @Override
                public void dispatchMessage(Message msg) {
                    if(msg.what == WHAT_BLOCK){
                        Log.i(MainActivity.TAG, "what block");
                        synchronized (lock){
                            super.dispatchMessage(msg);
                            lock.notify();
                            Log.i(MainActivity.TAG, "notify");
                        }
                    }
                    else{
                        super.dispatchMessage(msg);
                        Log.i(MainActivity.TAG, "what not block");
                    }
                }
            };
            weakHandler = new WeakReference<Handler>(handler);
            handler = null;
        }
    }

    public static void runOnUiThread(Context context, Runnable runnable){
        init(context);
        weakHandler.get().post(runnable);
        Log.i(MainActivity.TAG, "run ui over!");
    }

    public static void runOnUiThreadBlock(Context context, Runnable runnable){
        init(context);

        Message msg = Message.obtain(weakHandler.get(), runnable);
        msg.what = WHAT_BLOCK;
        msg.sendToTarget();

        synchronized (lock){
            Log.i(MainActivity.TAG, "begin wait!");
            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(MainActivity.TAG, "run ui block over!");
        }
    }

}

  主类MainActivity内容

package com.letv.handlertest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements View.OnClickListener {

    public static final String TAG = "HandlerTest";

    private Button btnRunOnUiThread, btnRunOnUiThreadBlock;
    private TextView tvShow1, tvShow2;
//    private RunUtilsB utils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

//        utils = new RunUtilsB(this);
    }

    private void initView(){
        btnRunOnUiThread = (Button)findViewById(R.id.btnRunOnUiThread);
        btnRunOnUiThreadBlock = (Button)findViewById(R.id.btnRunOnUiThreadBlock);
        tvShow1 = (TextView)findViewById(R.id.tvShow1);
        tvShow2 = (TextView)findViewById(R.id.tvShow2);

        btnRunOnUiThread.setOnClickListener(this);
        btnRunOnUiThreadBlock.setOnClickListener(this);
    }

    private void runUi(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                RunUtils.runOnUiThread(MainActivity.this, new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        tvShow1.setText("run ui");
                    }
                });
            }
        }).start();
    }

    private void runUiBlock(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                RunUtils.runOnUiThreadBlock(MainActivity.this, new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        tvShow2.setText("run ui block");
                    }
                });
            }
        }).start();
    }

    @Override
    public void onClick(View v) {
        if(v == btnRunOnUiThread){
            runUi();
        }
        else if(v == btnRunOnUiThreadBlock){
            runUiBlock();
        }
    }
}

 

运行结果正常。点击RunOnUiThread实现2s后更新textView1的值,点击调用后立马返回,点击RunOnUiThreadBlock后实现2s后更新textView2的值,更新完后才返回。

posted @ 2017-04-12 20:24  丛林小阁楼  阅读(493)  评论(0编辑  收藏  举报