Toast,AlertDialog的误解

在一般的软件开发中,子线程中是不能更改UI主线程中创建的UI控件的。之前的理解是Toast也不能在子线程中创建。事实上并不是这样子的。

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    new Thread(new Runnable(){

        @Override

        public void run() {

            // TODO Auto-generated method stub

            Toast.makeText(MainActivity.this, "test", Toast.LENGTH_LONG).show();

        }}).start();

}

在Activity的onCreate中写入以上代码运行。LogCat中会抱错

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

 

不看这个错误信息第一反应肯定是UI控件不能在子线程调用
事实上并不是这样的

我们可以查看Toast的源码

public Toast(Context context) {

        mContext = context;

        mTN = new TN();

        mTN.mY = context.getResources().getDimensionPixelSize(

                com.android.internal.R.dimen.toast_y_offset);

    }

    

    /**

     * Show the view for the specified duration.

     */

public void show() {

    if (mNextView == null) {

        throw new RuntimeException("setView must have been called");

    }



    INotificationManager service = getService();

    String pkg = mContext.getPackageName();

    TN tn = mTN;

    tn.mNextView = mNextView;

    try {

        service.enqueueToast(pkg, tn, mDuration);

    } catch (RemoteException e) {

            // Empty

    }

}

看这个mTN = new TN();构造函数

final Handler mHandler = new Handler();    

Handler的构造函数

public Handler(Callback callback, boolean async) {

       ...

        mLooper = Looper.myLooper();

        if (mLooper == null) {

            throw new RuntimeException(

                "Can't create handler inside thread that has not called Looper.prepare()");

        }

       ...

    }

而Looper.myLooper()

 /**

     * Return the Looper object associated with the current thread.  Returns

     * null if the calling thread is not associated with a Looper.

     */

    public static Looper myLooper() {

        return sThreadLocal.get();

    }

android中的子线程默认ThreadLocal中未设置Looper,所有会抛出这个异常,至于Looper是啥,可以参考我另一篇文章:http://www.cnblogs.com/cqcmdwym/archive/2013/05/12/3074138.html

解决方法

new Thread(new Runnable(){

    @Override

    public void run() {

        // TODO Auto-generated method stub

        Looper.prepare();

        Toast.makeText(MainActivity.this, "test", Toast.LENGTH_LONG).show();

        Looper.loop();

}}).start();

或者在主线程中声明一个Handler,然后在run方法中hanlder.post(new Runnable(){})一下。

同样AlertDialog也是如此,他包含一个AlertController字段,其内部也需要创建一个Handler.

参考网址:http://www.oschina.net/question/163910_31439

你可能感兴趣的:(AlertDialog)