您的位置:首页 > 运维架构

Can't create handler inside thread that has not called Looper.prepare()类型的错误及修改方法

2015-05-14 13:56 423 查看
首先将错误帖出来,(大概很多朋友都碰到过吧):

E/AndroidRuntime( 9874): FATAL EXCEPTION: Thread-1034
E/AndroidRuntime( 9874): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
E/AndroidRuntime( 9874):        at android.os.Handler.<init>(Handler.java:205)
E/AndroidRuntime( 9874):        at android.os.Handler.<init>(Handler.java:119)
E/AndroidRuntime( 9874):        at android.app.Dialog.<init>(Dialog.java:107)
E/AndroidRuntime( 9874):        at android.app.AlertDialog.<init>(AlertDialog.java:119)
E/AndroidRuntime( 9874):        at android.app.AlertDialog$Builder.create(AlertDialog.java:994)
E/AndroidRuntime( 9874):        at com.android.camera.ActivityBase.updateStorageHint(ActivityBase.java:871)
E/AndroidRuntime( 9874):        at com.android.camera.PhotoModule.updateCameraParametersPreference(PhotoModule.java:6274)
E/AndroidRuntime( 9874):        at com.android.camera.PhotoModule.setCameraParameters(PhotoModule.java:7059)
E/AndroidRuntime( 9874):        at com.android.camera.PhotoModule.startPreview(PhotoModule.java:5605)
E/AndroidRuntime( 9874):        at com.android.camera.PhotoModule.access$1400(PhotoModule.java:190)

E/AndroidRuntime( 9874):        at com.android.camera.PhotoModule$CameraStartUpThread.run(PhotoModule.java:627)

从上述调用栈上来看,就知道是一个 CameraStartUpThread 线程中跑了关于UI显示方面的东东导致的。Android app层规定的比较死板,

一般在非 UI 的线程中不允许调弹出框,对话框之类的东东。而在上述错误中正是由于 ActivityBase.java 类的 updateStorageHint() 函数中创建了一个对话框导致的,而这个函数又被非 UI 线程 CameraStartUpThread 间接调用 。

要解决此问题也非常简单:

方法一,将对话框创建的地方放在 UiThread 中跑。

[java] view
plaincopy





AlertDialog.Builder builder = new AlertDialog.Builder(this);  

builder.setCancelable(false)  

        .setTitle(getString(R.string.not_enough_dialog_title))  

        .setMessage(message)  

        .setNeutralButton(R.string.not_enough_dialog_clear,  

                new DialogInterface.OnClickListener() {  

                    @Override  

                    public void onClick(DialogInterface dialog, int which) {  

                        startActivity(clearIntent);  

                    }  

                })  

        .setNegativeButton(android.R.string.cancel,  

                new DialogInterface.OnClickListener() {  

                    @Override  

                    public void onClick(DialogInterface dialog, int which) {  

                        finish();  

                    }  

                });  

源代码:

[java] view
plaincopy





if (mNeedClearRotateDialog == null || !mNeedClearRotateDialog.isShowing()) {  

                mNeedClearRotateDialog = builder.create();  

            }  

改为:

[java] view
plaincopy





if (mNeedClearRotateDialog == null || !mNeedClearRotateDialog.isShowing()) {  

                mActivity.runOnUiThread(new Runnable() {  

                    public void run() {  

                        mNeedClearRotateDialog = builder.create();  

                    }  

                });  

            }  

注:如果当前类不是 Activity 类的话,还需要在 runOnUiThread 前加上 mActivity 类对象来调用,如上所示。另外该 Runnable() 是一个匿名线程,该线程中变量需要是 final 类型的。这里还需要将 builder 变量改为 final 类型的。

方法二:在 CameraStartupThread() 一开始调用的地方就加上runOnUiThread

源码:

[java] view
plaincopy





checkStoragePathPreference(mPreferences);  

if (mActivity != null) {  

    Long leftSpace = Storage.getAvailableSpace();  

vity.updateStorageHint(leftSpace);  

}  

改为:

[java] view
plaincopy





    checkStoragePathPreference(mPreferences);  

    if (mActivity != null) {  

        final Long leftSpace = Storage.getAvailableSpace();  

        mActivity.runOnUiThread(new Runnable() {  

public void run() {           

    mActivity.updateStorageHint(leftSpace);  

}  

        });  

    }  

再次重申匿名线程中的变量需要改为 final 类型的,不然会报错。

相对而言,推荐方法一,这样影响的地方比较小,如果在 mAcitivity.updateStorageHint(leftSpace) 函数调用中没有什么复杂的逻辑的话方法二也是可行的。

UiThread 一般都是用于界面显示的一些东西,不要把一些复杂的计算或者耗电的逻辑放到其中。如果有比较耗时的操作的话就建议新开线程来在后台做了。

很多 ANR 都是来源于主线程中跑了一些比较耗时耗资源的操作,导致按键响应不及时,或者等待过久 发生的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐