溪源小常识 發表於 2025-7-24 09:49:44

Android Studio切换主线程的两种方式详解

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>1. runOnUiThread()</li><li>2. Handler.post()</li></ul></div><p>在&nbsp;Android&nbsp;中,<strong>UI 操作必须在主线程</strong>中进行,不能直接在子线程中更新 UI。今天介绍两种在子线程切换回主线程的方法。</p>
<p><code>runOnUiThread()</code> 和 <code>Handler.post()</code> 都可以用于切换到 <strong>主线程(UI 线程)</strong> 执行任务,主要用于 <strong>更新 UI</strong>。但它们在<strong>使用方式、作用范围、底层实现</strong>上有所不同。</p>
<p class="maodian"></p><h2>1. runOnUiThread()</h2>
<p><code>runOnUiThread()</code> 是 <code>Activity</code> 的一个方法,它可以让任务在 <strong>主线程(UI 线程)</strong> 执行。<strong>适用于</strong> 在 <code>Activity</code> 内部 <strong>从子线程切换到主线程</strong> 以更新 UI。</p>
<p>用法:</p>
<div class="jb51code"><pre class="brush:java;">runOnUiThread(new Runnable() {
    @Override
    public void run() {
      textView.setText("更新 UI");
    }
});
</pre></div>
<p>Lambda 写法:</p>
<div class="jb51code"><pre class="brush:java;">runOnUiThread(() -&gt; textView.setText("更新 UI"));
</pre></div>
<p><strong>底层原理:</strong></p>
<p><code>runOnUiThread()</code> 的实现本质上 <strong>使用了 <code>Handler.post()</code></strong>,它会获取 <code>Activity</code> 绑定的 <code>Looper</code>,然后将任务投递到 <strong>主线程消息队列</strong>。</p>
<p><strong>适用场景</strong></p>
<ul><li><strong>只在 <code>Activity</code> 里使用</strong>,不能在 <code>Service</code>、<code>BroadcastReceiver</code> 等组件中用。</li><li><strong>简单的 UI 更新</strong>,比如在 <code>onCreate()</code>、网络请求回调、异步任务完成后 <strong>更新 TextView、Button 等 UI 组件</strong>。</li></ul>
<p>完整的代码:实现的效果很简单,2秒后在主界面更新UI,显示 &quot;UI 更新成功!&quot;</p>
<div class="jb51code"><pre class="brush:java;">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();
    }
}</pre></div>
<p class="maodian"></p><h2>2. Handler.post()</h2>
<p><code>Handler.post()</code> 通过 <code>Handler</code> <strong>将任务投递到指定的线程</strong>,一般用于 <strong>从子线程切换到主线程</strong> 处理 UI 更新,也可以用于子线程间通信。</p>
<div class="jb51code"><pre class="brush:java;">Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -&gt; textView.setText("更新 UI"));
</pre></div>
<p><strong>底层原理</strong></p>
<ul><li><code>Handler</code> 通过 <code>MessageQueue</code> <strong>投递任务</strong>,<code>Looper</code> 取出并执行。</li><li><strong>不会判断当前线程</strong>,即使 <code>post()</code> 发生在主线程,它也会把任务<strong>加入消息队列</strong>,可能稍微延迟执行。</li></ul>
<p><strong>适用场景</strong></p>
<ul><li>适用于 <strong>所有 Android 组件</strong>(<code>Activity</code>、<code>Service</code>、<code>Fragment</code>、<code>BroadcastReceiver</code>)。</li><li><strong>可以执行延迟任务</strong>(<code>postDelayed()</code>)。</li><li><strong>可在子线程和子线程间通信</strong>,不仅限于 UI 更新。</li></ul>
<p>完整代码,实现的效果和上面runOnUiThread()是一样的。2秒延迟后,主界面显示&quot;数据加载完成&quot;</p>
<div class="jb51code"><pre class="brush:java;">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(() -&gt; {
            try {
                Thread.sleep(2000); // 模拟网络请求
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(() -&gt; textView.setText("数据加载完成"));
      }).start();

    }
}</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025072409455633.png" /></p>
<p>到此这篇关于Android Studio切换主线程的两种方式详解的文章就介绍到这了,更多相关Android Studio切换主线程内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Android源码导入AndroidStudio或IntelliJ IDEA的方法</li><li>基于IntelliJ IDEA/Android Studio插件开发指南(推荐)</li><li>初步编写IDEA\AndroidStudio翻译插件的方法</li><li>Android Studio IDE升级4.1以后Start Failed</li><li>Android Studio / IDEA kotlin 显示 var 真实类型操作</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Android Studio切换主线程的两种方式详解