首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android子線程更新UI崩潰:Handler機制與runOnUiThread解決方案

     編輯:程式設計綜合問答

錯誤原因

Thread中直接調用TextView.setText() → CalledFromWrongThreadException:Android UI工具包非線程安全,**只有UI線程能訪問View**。

三種修正方案

  1. Handler(經典):
    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override public void handleMessage(Message msg) {
            textView.setText("更新內容");
        }
    };
    // 子線程發送消息
    new Thread(() -> {
        handler.sendEmptyMessage(0);
    }).start();
  2. runOnUiThread(Activity專用):
    runOnUiThread(() -> textView.setText("更新內容"));
  3. View.post(Runnable)(通用):
    textView.post(() -> textView.setText("更新內容"));

代碼重構示例

public class MainActivity extends Activity {
    TextView sendView, receiveView;
    Handler handler = new Handler(Looper.getMainLooper());
    boolean flag = false;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ... findViewById ...
        Button btnStart = findViewById(R.id.send);
        btnStart.setOnClickListener(v -> {
            flag = true;
            new Thread(this::backgroundTask).start();
        });
    }
    
    void backgroundTask() {
        for (int i = 1; i <= 100 && flag; i++) {
            final int value = i;
            handler.post(() -> { // 切換到主線程
                sendView.setText(String.valueOf(value));
                receiveView.setText(String.valueOf(value));
            });
            try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
        }
    }
}

關鍵點

  • Thread.sleep在子線程正常,主線程會ANR。
  • Handler持有Looper引用,Looper.getMainLooper()綁定主線程消息隊列。
  • 內存洩漏防範:static class MyHandler extends Handler + WeakReference,或removeCallbacksAndMessages(null)在onDestroy。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved