1. 程式人生 > >為啥Toast在子執行緒報錯

為啥Toast在子執行緒報錯

剛開始學習android的同學們,都應該知道Log,和Toast這兩個類,因為這兩個類經常用來,給我檢視程式碼的執行情況,所以有些時候,就會導致用起來混淆的情況,Log的話,沒什麼限制,在任何的方法下都可以使用,當然使用Log的時候,記得標記TAG,不要直接寫“TAG”,一般情況下,直接下類名的,這樣的話,就方便將來去找相應的Log,當然,你也可以給Log加一個開關,當你的專案完成,log開關一關,那麼所有的Log就消失的無影無蹤了。
Toast,一般在主執行緒使用的時候,沒有多大的問題,可是一旦到子執行緒中,就有可能報錯。那麼這是什麼原因呢?
那麼咱們就來看看Toast的原始碼

  public Toast(Context context) {
        mContext = context;
mTN = new TN(); mTN.mY = context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.toast_y_offset); mTN.mGravity = context.getResources().getInteger( com.android.internal.R.integer.config_toastDefaultGravity); }

咋一看,什麼玩意,就弄倆物件,第一個沒啥可講的,第二TN類,什麼破類,咱們接著點。。。

  private static class TN extends ITransientNotification.Stub {
....
        看這裡   ***final Handler mHandler = new Handler();***    
....

        }

Handler!眼前一亮,我們都知道Handler的使用,需要和Loop配合,假如在主執行緒中,那麼Handler是直接可以new的,因為主執行緒中自帶的有Loop,而普通的執行緒是沒有Loop的(如果你不知道,那麼你現在應該知道了),所以Toast在主執行緒使用的時候,就不會報錯,那麼為啥子執行緒中就會報錯呢?

咱麼繼續點Handler

    public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

有木有,大家看到了這個沒有

    if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }

如果Looper為null的時候,就會丟擲這個異常,前面咱們也說了,普通執行緒是不會建立Loop的(除了主執行緒),所有Loop自然就是null的,所以子執行緒中使用Toast就會報錯!

既然找到了原因,那麼就有了解決的方法:
1、既然在主執行緒中使用,不會報錯,那麼咱們就在主執行緒使用唄!

public class MainActivity extends Activity {
    private static final int TAG_TOAST = 0;
    private Handler mHandler = new Handler(){

        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case TAG_TOAST:
                Toast.makeText(MainActivity.this, msg.obj.toString(), Toast.LENGTH_SHORT).show();
                break;

            default:
                break;
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

public void onClick(View view){
            new Thread(){
            public void run() {
                Message _Message = mHandler.obtainMessage();
                _Message.what = TAG_TOAST;
                _Message.obj = "在子執行緒中Toast!";
                mHandler.sendMessage(_Message);
            };
        }.start();
}

}

2、既然子執行緒中沒有Loop,那麼咱們給他建立一個不就得了嘛,開始幹!

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

public void onClick(View view){
            new Thread(){
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this, msg.obj.toString(), Toast.LENGTH_SHORT).show();
                Looper.loop();
Toast.makeText(MainActivity.this, msg.obj.toString(), Toast.LENGTH_SHORT).show();
            };
        }.start();
}

}

你猜猜上面的子執行緒中會Toast的幾次,兩次,哈哈,錯了,一次,因為第二種方法有個缺點就是Looper.loop();後面的方法得不到執行,當然也可以呼叫Looper.myLooper().quit();推出Looper,那麼後面的方法就會繼續執行了。

相關推薦

為啥Toast執行

剛開始學習android的同學們,都應該知道Log,和Toast這兩個類,因為這兩個類經常用來,給我檢視程式碼的執行情況,所以有些時候,就會導致用起來混淆的情況,Log的話,沒什麼限制,在任何的方法下都可以使用,當然使用Log的時候,記得標記TAG,不要直接寫“

Android進階(十六)執行呼叫ToastCan't create handler inside thread that has not called Looper.prepare() 錯誤

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

執行中new Handler--Can't create handler inside thread that has not called Looper.prepare()

在子執行緒中new一個Handler為什麼會報以下錯誤? java.lang.RuntimeException:  Can't create handler inside thread that has not&

python在執行中使用WMI-2147221020-moniker,i,bindCTX=pythoncom.MKParseDisplayName(Pathname) ——轉載

判斷電腦是否存在某程序: #check_exsit def check_exsit(process_name):       #線上程中使用需要加初始化和去初始化方法      pythoncom.CoInitialize() &nbs

【轉】在執行中new Handler--Can't create handler inside thread that has not called Looper.prepare()

在子執行緒中new一個Handler為什麼會報以下錯誤? java.lang.RuntimeException:  Can't create handler inside thread that has not ca

執行Handler sendMessage Attempt to invoke virtual method '

                03-17 08:10:18.760 16029-16029/tech.androidstudio.tulingdemo E/AndroidRuntime: FATAL EXCEPTION: main03-17 08:10:18.760 16029-16029/tech.and

執行Handler.sendMessage :Attempt to invoke virtual method 'boolean android.os.Handler.sendMessage

03-17 08:10:18.760 16029-16029/tech.androidstudio.tulingdemo E/AndroidRuntime: FATAL EXCEPTION: main 03-17 08:10:18.760 16029-16029/tech.

執行新建Handler為什麼會?——淺談Handler、Looper、Message關係

轉載註明出處: 很多人都知道不能直接在子執行緒new 一個Handler,android會報錯,至於為什麼會報錯,並沒有做深入的研究,今天就來研究一下,順手學習了下android非同步訊息處理機制的問題,一起放出來。 常見面試題

Android進階(十六)執行呼叫ToastCan't create handler inside thread that has not called Looper.prepare() 錯誤

原子執行緒呼叫Toast報Can't create handler inside thread that has not called Looper.prepare() 錯誤 今天用子執行緒調Toast報了一個Can't create handler inside thre

toast彈框、imageview、進度條、執行訪問主執行執行中的通訊handler)

1、imageview ?xml version="1.0" encoding="utf-8"?> <ImageView android:layout_width=“200dp” android:layout_marginLeft=“100dp” an

執行中使用Toast或者更新UI(轉)

Toast只能在主UI執行緒使用,使用下面的辦法可以解決 第一種,使用Looper,不過這種辦法會終止,子執行緒之後的程式碼 Looper.prepare(); Toast.makeText(aActivity.this,"test",Toast.LENGTH_SHOR

centos 7 執行 groupinstall

ges tap armv7 dev erro http system package org 報錯顯示Error: Package: systemtap-devel-3.10-10.el7.armv7hl (base) Requires: kernel-devel 解決方案

Oracle執行SQLORA-00922

log define sql option -1 nbsp 執行sql 問題 val 問題描述: 對Oracle數據庫執行序列化腳本出錯,ora-00922 missing or invalid option #無效的選項 問題解決:

eclipse下執行wordcount java.lang.ClassNotFoundException 解決辦法

eclipse下執行wordcount報錯 java.lang.classnotfoundexception 解決辦法eclipse下執行wordcount報錯 java.lang.ClassNotFoundException17/08/29 07:52:54 INFO Configuration.depre

執行setup, -bash: setup: command not found

配置 xshell localhost 工具 host work ins lan uri 執行setup,報錯。 [root@localhost ~]# setup -bash: setup: command not found 出現這個問題的是因為沒有安裝setuptoo

SSH執行hql:Caused by: org.hibernate.hql.ast.QuerySyntaxException: user is not mapped [from user where username = ?]

執行 occurred ble xml文件 ron red 報錯 temp caused 報錯信息: ERROR Dispatcher:38 - Exception occurred during processing request: user is not mapped

django中執行pyRequested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured

setting 執行 添加 all ted tables IT clas core https://blog.csdn.net/heybob/article/details/49684261 django代碼下面直接run的時候報錯: django.core.excepti

Failed to execute 'toDataURL' on 'HTMLCanvasElement,在canvas.toDataURL()執行時候解決方案

from info long allow 條件 star The cross can 添加跨域條件 crossorigin="anonymous" 【Redirect at origin ‘http://xxx.xx.com‘ has been block

Android執行模型--在執行中更新UI

       Android是支援多執行緒的。主執行緒也稱UI執行緒,子執行緒也稱工作執行緒。一般耗時操作在子執行緒中進行,更新UI操作在主執行緒中進行。在主執行緒中執行耗時操作容易發生ANR錯誤,即應用程式無響應。而Android中又規定只有建立UI的執行緒

C# 解決執行不能操作主執行UI(介面)問題,涉及到多執行的概念。

1、在預設情況下,C#不准許在一個執行緒中直接訪問或操作另一執行緒中建立的控制元件,這是因為訪問windows窗體控制元件本質上是不安全的。 2、執行緒之間是可以同時執行的,那麼如果有兩個或多個執行緒同時操作某一控制元件的某狀態,嘗試將一個控制元件變為自己需要的狀態時, 執行緒的死鎖就可能發生。