实现RunOnUiThread和RunOnUiThreadBlock

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

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

RunUtils内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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 @   丛林小阁楼  阅读(514)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示