ExceptionInInitializerError & 无法在未调用 Looper.prepare() 的线程内创建处理程序

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

1.I 想在话题中吐司

2.and 我设置了 Looper.getMainLooper()

但还是崩溃了 我知道可以使用 activity.runOnUiThread 解决这个问题 但我想另找方法解决,改成ToastUtil.

拜托,提前致谢

public class ToastUtil {

private static Toast toast = Toast.makeText(MainApplication.getApp(),"",Toast.LENGTH_SHORT);
private static Toast scrollToast = Toast.makeText(MainApplication.getApp(),"",Toast.LENGTH_SHORT);

public static void show(final String src) {
    if (StringUtils.isEmpty(src)) {
        return;
    }
    r.post(new Runnable() {
        @Override
        public void run() {
            toast.setText(src);
            toast.show();
        }
    });
    Logger.d("Toast", src);
}

public static void show(int resId) {
    final String src;
    src = MainApplication.getApp().getResources().getString(resId);
    if (StringUtils.isEmpty(src)) {
        return;
    }
    r.post(new Runnable() {
        @Override
        public void run() {
            toast.setText(src);
            toast.show();
        }
    });
}

public static void showScrollToast(final String src) {
    final View toastRoot = LayoutInflater.from(MainApplication.getApp()).inflate(R.layout.widget_view_toast, null);
    MyTextView textView = (MyTextView) toastRoot.findViewById(R.id.scroll_toast);
    textView.setText(src);
    r.post(new Runnable() {
        @Override
        public void run() {
            scrollToast.setGravity(Gravity.FILL_HORIZONTAL | Gravity.TOP, 0, DisplayMetricsTools.dp2px(50));
            scrollToast.setDuration(Toast.LENGTH_LONG);
            scrollToast.setView(toastRoot);
            scrollToast.show();
        }
    });

}

private static Handler r = new Handler(Looper.getMainLooper());}

崩溃日志:

 java.lang.ExceptionInInitializerError
                                                 at com.utils.ToastUtil.show(ToastUtil.java:24)
                                                 at com.utils.ErrorInfo.showError(ErrorInfo.java:43)
                                                 at com.integration.CreateBoardActivity.allotModerators(CreateBoardActivity.java:392)
                                                 at com.integration.CreateBoardActivity.access0(CreateBoardActivity.java:72)
                                                 at com.duodian.morespace.integration.CreateBoardActivity.run(CreateBoardActivity.java:371)
                                                 at java.lang.Thread.run(Thread.java:761)
                                              Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
                                                 at android.os.Handler.<init>(Handler.java:200)
                                                 at android.os.Handler.<init>(Handler.java:114)
                                                 at android.widget.Toast$TN.<init>(Toast.java:336)
                                                 at android.widget.Toast$TN.<init>(Toast.java:336)
                                                 at android.widget.Toast.<init>(Toast.java:103)
                                                 at android.widget.Toast.makeText(Toast.java:256)
                                                 at com.utils.ToastUtil.<clinit>(ToastUtil.java:20)
                                                 at com.utils.ToastUtil.show(ToastUtil.java:24) 
                                                 at com.utils.ErrorInfo.showError(ErrorInfo.java:43) 
                                                 at com.integration.CreateBoardActivity.allotModerators(CreateBoardActivity.java:392) 
                                                 at com.integration.CreateBoardActivity.access0(CreateBoardActivity.java:72) 
                                                 at com.integration.CreateBoardActivity.run(CreateBoardActivity.java:371) 
                                                 at java.lang.Thread.run(Thread.java:761) 

问题不在于 ToastUtil 中的 Handler,而是 Toast 中的 Handler

Toast 的构造函数中创建了 TN 的实例。

public Toast(Context context) {
    mContext = context;
    mTN = new TN();
    ......
}

并且 TN 包含一个成员字段,它是一个处理程序。

private static class TN extends ITransientNotification.Stub {
    ......
    final Handler mHandler = new Handler();  
    ......
}  

当您第一次在普通线程中使用 ToastUtil 时,TN 的处理程序将在该线程中初始化,没有导致崩溃的循环程序。

您应该在主线程或具有循环程序的线程中使用 ToastUtil

只需更改 ToastUtil 即可解决。

不要使 toastscrollToast 静态 而是在方法 showshowScrollToast 中实例化它们。例如

public static void show(final String src) {
    if (StringUtils.isEmpty(src)) {
        return;
    }
    r.post(new Runnable() {
        @Override
        public void run() {
            Toast toast = Toast.makeText(MainApplication.getApp(),"",Toast.LENGTH_SHORT);
            toast.setText(src);
            toast.show();
       }
    });
    Logger.d("Toast", src);
}

我认为以这种方式使用实用程序会更好:

public class ToastUtil {
    //if you don't care about the toast style you can pass the Application
    //context instead of the Activity one
    public static void show(Context context, @StringRes int stringRes) {
        String message = context.getResources().getString(stringRes);
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
        Logger.d("Toast", message);
    }
}

然后像这样使用:

ToastUtil.show(context, R.string.my_message);

如果你想完全忽略Activity风格,你应该在传递Application的class中添加一个构造函数,然后你可以调用每个静态方法而不需要一遍又一遍地传递上下文。 (或者您可以在每个 Activity 扩展的 BaseActivity 中初始化此实用程序)