Android中非UI主線程能不能操作UI?

問題:“Android只能在UI線程更新UI 么?”
答:“對(duì)!......,嗯?不對(duì)?”
我腦子里的的回答是“對(duì)”,但是辯證思維又在提醒我可能有陷阱,于是我就說“大部分情況是的”。那么小部分情況呢?具體說不上來了!于是才發(fā)現(xiàn)這個(gè)問題一直被忽略了。
于是試驗(yàn)檢驗(yàn)真理,擼代碼驗(yàn)證了一遍。


new Thread(){
    @Override
    public void run() {
        super.run();
        btn_demo1.setText("Demo1--"+Thread.currentThread().getName());
    }
}.start();

奔潰信息:


CalledFromWrongThreadException

問題出現(xiàn)在ViewRootImpl.checkThread()的時(shí)候出錯(cuò)
查看ViewRootImpl的源碼,導(dǎo)致問題的原因:

 public ViewRootImpl(Context context, Display display) {
        mContext = context;
         mWindowSession = WindowManagerGlobal.getWindowSession();
       mDisplay = display;
       mBasePackageName = context.getBasePackageName();
       mThread = Thread.currentThread();
              .......
}
 @Override
     public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
             mLayoutRequested = true;
             scheduleTraversals();
         }
     }
 
void checkThread() {
         if (mThread != Thread.currentThread()) {
             throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
     }

ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
CalledFromWrongThreadException提示:只能在創(chuàng)建View的線程里操作view.
那么意思是我在非主線程創(chuàng)建View,就可以在非主線程操作該view了咯!
于是:

private void addWindView(){
    TextView tx = new TextView(MainActivity.this);
    tx.setText("今天天氣很好哦!");
    tx.setTextColor(getResources().getColor(R.color.white));
    tx.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
    tx.setGravity(Gravity.CENTER);
    WindowManager wm = MainActivity.this.getWindowManager();
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            250, 150, 200, 200, WindowManager.LayoutParams.FIRST_SUB_WINDOW,
            WindowManager.LayoutParams.TYPE_TOAST, PixelFormat.OPAQUE);
    wm.addView(tx, params);
}
new Thread(){
    @Override
    public void run() {
        super.run();
        addWindView();
    }
}.start();

不幸的是,還是崩了。
崩潰信息:


not call Looper.perpare()

源碼中:
void checkThread() 通過了,可是在scheduleTraversals()刷新UI的時(shí)候:

 final ViewRootHandler mHandler = new ViewRootHandler(); 
  .......
  void scheduleTraversals() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
             mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
             mChoreographer.postCallback(
                     Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                 scheduleConsumeBatchedInput();
             }
             notifyRendererOfFramePending();
             pokeDrawLockIfNeeded();
       }
     }

所以沒有Looper實(shí)例化的異常。
于是加上Looper.perpare(),和Looper.loop().

new Thread(){
    @Override
    public void run() {
        super.run();
        Looper.perpare()
        addWindView();
        Looper.loop()
    }
}.start();

這下沒有報(bào)錯(cuò)并且成功加載顯示UI.


所以,Android中非UI主線程能不能操作UI?答案是可以的。只不過只能在創(chuàng)建View的線程里操作view.

總結(jié):

1.由于Android是通過Handler消息機(jī)制的方式刷新UI的。所以Android 的UI控件是線程安全的,不會(huì)導(dǎo)致多線程訪問使得UI處于不可預(yù)期的狀態(tài)。
2.Android每次刷新UI的時(shí)候,最終根布局ViewRootImpl.checkThread()來檢驗(yàn)線程是否是View的創(chuàng)建線程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,058評(píng)論 25 709
  • 【Android Handler 消息機(jī)制】 前言 在Android開發(fā)中,我們都知道不能在主線程中執(zhí)行耗時(shí)的任務(wù)...
    Rtia閱讀 5,091評(píng)論 1 28
  • 本篇文章已授權(quán)微信公眾號(hào) guolin_blog (郭霖)獨(dú)家發(fā)布 這次就來梳理一下 Android 的屏幕刷新機(jī)...
    請(qǐng)叫我大蘇閱讀 26,114評(píng)論 48 206
  • 1.概述 ? Android的消息機(jī)制主要是指Hanlder的運(yùn)行機(jī)制及其附帶的MessageQueue和Lo...
    GordenNee閱讀 2,019評(píng)論 0 7
  • 不知何因,我總感覺饑餓與困盹?旅行歸來,收拾散亂的心,卻讓自己更加懶散,想睡,做點(diǎn)事就覺得累,一下來,就想吃東西充...
    王澤華wzh閱讀 192評(píng)論 0 0

友情鏈接更多精彩內(nèi)容