Toast不能直接在子線程中使用

new Thread(){
    public void run(){
        Toast.makeText(public_log.this,"圖片不存在",Toast.LENGTH_SHORT).show();
    }
}

如果像這樣直接在子線程中彈出Toast,程序會報(bào)錯(cuò)铸磅。

深入源碼了解一下原因:

  public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
    Toast result = new Toast(context);

    LayoutInflater inflate = (LayoutInflater)
            context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
    TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
    tv.setText(text);

    result.mNextView = v;
    result.mDuration = duration;

    return result;
}

makeText方法好像沒有什么不對赡矢,那么繼續(xù)向下看show()方法

   public void show() {
    if (mNextView == null) {
        throw new RuntimeException("setView must have been called");
    }

    INotificationManager service = getService();
    String pkg = mContext.getOpPackageName();
    TN tn = mTN;
    tn.mNextView = mNextView;

    try {
        service.enqueueToast(pkg, tn, mDuration);
    } catch (RemoteException e) {
        // Empty
    }
}

好像沒什么不對 但是看getService()不對勁就點(diǎn)擊進(jìn)去看一下

  static private INotificationManager getService() {
    if (sService != null) {
        return sService;
    }
    sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
    return sService;
}

這里還是看不出有什么問題 然而show()里面這個(gè)又一次引起了我的注意

TN tn = mTN;

我點(diǎn)擊進(jìn)去查看源碼,好家伙終于發(fā)現(xiàn)問題所在了

 private static class TN extends ITransientNotification.Stub {
    final Runnable mShow = new Runnable() {
        @Override
        public void run() {
            handleShow();
        }
    };

    final Runnable mHide = new Runnable() {
        @Override
        public void run() {
            handleHide();
            // Don't do this in handleHide() because it is also invoked by handleShow()
            mNextView = null;
        }
    };

    private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
    final Handler mHandler = new Handler();

    阅仔。吹散。。八酒。空民。代碼省略。羞迷。界轩。。衔瓮。浊猾。


    /**
     * schedule handleShow into the right thread
     */
    @Override
    public void show() {
        if (localLOGV) Log.v(TAG, "SHOW: " + this);
        mHandler.post(mShow);
    }

    /**
     * schedule handleHide into the right thread
     */
    @Override
    public void hide() {
        if (localLOGV) Log.v(TAG, "HIDE: " + this);
        mHandler.post(mHide);
    }

    。热鞍。葫慎。衔彻。。代碼省略偷办。艰额。。椒涯。柄沮。。
}

我相信聰明的你們應(yīng)該看到了這里為什么錯(cuò)了废岂,對祖搓,就是Handler不能再子線程里運(yùn)行的 因?yàn)樽泳€程沒有創(chuàng)建Looper.prepare(); 所以就報(bào)錯(cuò)了。主線程不需要調(diào)用泪喊,是因?yàn)橹骶€程已經(jīng)默認(rèn)幫你調(diào)用了棕硫。

可以看到一個(gè)Toast的創(chuàng)建需要依賴Handler髓涯。那么 我不要 我不要 我一定要在子線程使用Toast那怎么辦袒啼。

其實(shí)很簡單,它卻什么就給它什么纬纪。
第一種方法

  new Thread(){
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            try {
                Toast.makeText(MainActivity.this,"ceshi",Toast.LENGTH_SHORT).show();
            }catch (Exception e) {
                Logger.e("error",e.toString());
            }
            Looper.loop();
        }
    }.start();

因?yàn)槌薃ctivity ui線程默認(rèn)創(chuàng)建之外蚓再,其他線程不會自動創(chuàng)建調(diào)用 Looper.prepare()來給線程創(chuàng)建消息循環(huán),然后再通過包各,Looper.loop()來使消息循環(huán)起作用劈愚。

第二種方法就是

  runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(MainActivity.this,"ceshi23333",Toast.LENGTH_SHORT).show();
        }
    });
    new Thread(){

    }.start();

Toast的代碼創(chuàng)建在Runnable中扭仁,然后在需要Toast時(shí),把這個(gè)Runnable對象傳給runOnUiThread(Runnable)。 這樣Runnable對像就能在ui程序中被調(diào)用肚菠。如果當(dāng)前線程是UI線程,那么行動是立即執(zhí)行

第三種方法和第一張差不多

  Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        //這里寫你的Toast代碼
        }
    };

    new Thread(){
        @Override
        public void run() {
            super.run();
            mHandler.sendEmptyMessage(0);
        }
    }.start();

另:在非主線程中直接new Handler() 會報(bào)如下的錯(cuò)誤: E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 原因是非主線程中默認(rèn)沒有創(chuàng)建Looper對象,需要先調(diào)用Looper.prepare()啟用Looper诉探。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末先较,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子卵皂,更是在濱河造成了極大的恐慌秩铆,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灯变,死亡現(xiàn)場離奇詭異殴玛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)添祸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門滚粟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人刃泌,你說我怎么就攤上這事凡壤±⒐担” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵鲤遥,是天一觀的道長沐寺。 經(jīng)常有香客問我,道長盖奈,這世上最難降的妖魔是什么混坞? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮钢坦,結(jié)果婚禮上究孕,老公的妹妹穿的比我還像新娘。我一直安慰自己爹凹,他們只是感情好厨诸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著禾酱,像睡著了一般微酬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颤陶,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天颗管,我揣著相機(jī)與錄音,去河邊找鬼滓走。 笑死垦江,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搅方。 我是一名探鬼主播比吭,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姨涡!你這毒婦竟也來了衩藤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绣溜,失蹤者是張志新(化名)和其女友劉穎慷彤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怖喻,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡底哗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锚沸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跋选。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哗蜈,靈堂內(nèi)的尸體忽然破棺而出前标,到底是詐尸還是另有隱情坠韩,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布炼列,位于F島的核電站只搁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俭尖。R本人自食惡果不足惜氢惋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望稽犁。 院中可真熱鬧焰望,春花似錦、人聲如沸已亥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虑椎。三九已至震鹉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绣檬,已是汗流浹背足陨。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工嫂粟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娇未,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓星虹,卻偏偏與公主長得像零抬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子宽涌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容