Android Studio:切换主线程的两种方式runOnUiThread、Handler.post

发布于:2025-02-21 ⋅ 阅读:(29) ⋅ 点赞:(0)

        之前介绍handler的时候讲过,在 Android 中,UI 操作必须在主线程中进行,不能直接在子线程中更新 UI。今天介绍两种在子线程切换回主线程的方法。

        runOnUiThread()Handler.post() 都可以用于切换到 主线程(UI 线程) 执行任务,主要用于 更新 UI。但它们在使用方式、作用范围、底层实现上有所不同。

1. runOnUiThread()

  runOnUiThread()Activity 的一个方法,它可以让任务在 主线程(UI 线程) 执行。适用于Activity 内部 从子线程切换到主线程 以更新 UI。

用法:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        textView.setText("更新 UI");
    }
});

Lambda 写法:

runOnUiThread(() -> textView.setText("更新 UI"));

底层原理:

  runOnUiThread() 的实现本质上 使用了 Handler.post(),它会获取 Activity 绑定的 Looper,然后将任务投递到 主线程消息队列

适用场景

  • 只在 Activity 里使用,不能在 ServiceBroadcastReceiver 等组件中用。
  • 简单的 UI 更新,比如在 onCreate()、网络请求回调、异步任务完成后 更新 TextView、Button 等 UI 组件

完整的代码:实现的效果很简单,2秒后在主界面更新UI,显示 "UI 更新成功!"

public class MainActivity extends AppCompatActivity {

    private TextView textView;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main9);

        textView = findViewById(R.id.textView);

        // 在子线程中执行耗时操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000); // 模拟网络请求或其他耗时任务
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 切换到主线程更新 UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("UI 更新成功!");
                    }
                });
            }
        }).start();
    }
}

2. Handler.post()

Handler.post() 通过 Handler 将任务投递到指定的线程,一般用于 从子线程切换到主线程 处理 UI 更新,也可以用于子线程间通信。

Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> textView.setText("更新 UI"));

底层原理

  • Handler 通过 MessageQueue 投递任务Looper 取出并执行。
  • 不会判断当前线程,即使 post() 发生在主线程,它也会把任务加入消息队列,可能稍微延迟执行。

适用场景

  • 适用于 所有 Android 组件ActivityServiceFragmentBroadcastReceiver)。
  • 可以执行延迟任务postDelayed())。
  • 可在子线程和子线程间通信,不仅限于 UI 更新。

完整代码,实现的效果和上面runOnUiThread()是一样的。2秒延迟后,主界面显示"数据加载完成"

import android.os.Handler;
import android.os.Looper;

public class MainActivity extends AppCompatActivity {

    private TextView textView;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main9);

        textView = findViewById(R.id.textView);

        Handler handler = new Handler(Looper.getMainLooper());
        new Thread(() -> {
            try {
                Thread.sleep(2000); // 模拟网络请求
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(() -> textView.setText("数据加载完成"));
        }).start();

    }
}


网站公告

今日签到

点亮在社区的每一天
去签到