java.lang.RuntimeException: Can't create handler inside thread that has not

在子线程中 调用了这句:

Toast.makeText(UiUtils.getContext(), "正在下载"+name, Toast.LENGTH_SHORT).show();

报出了下面的错误

08-15 14:52:50.368 3517-3560/com.ldw.marketm E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-5
    Process: com.ldw.marketm, PID: 3517
    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:327)
        at android.widget.Toast.<init>(Toast.java:92)
        at android.widget.Toast.makeText(Toast.java:241)
        at com.ldw.marketm.holder.DetailBottomHolder$2.run(DetailBottomHolder.java:78)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)

分析:跟踪源码

查看makeText方法,可以看到 new了一个Toast实例

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;
}

Toast构造函数中又实例化了一个 TN对象

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中,可以读到这一句:

final Handler mHandler = new Handler();

创建了一个Handler对象

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();

读 Handler构造函数:

/**
 * * Default constructor associates this handler with the {@link Looper} for
 * the * current thread. * * If this thread does not have a looper, this
 * handler won't be able to receive messages * so an exception is thrown.
 */
public Handler() {
    this(null, false);
}

继续后面

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;
}

主线程中创建handler后会默认创建一个looper对象。但是子线程不会,需要手动创建。其ThreadLoacl中没有设置过Looper,mLooper==null ,所以会抛出异常。

解决方法

方法一:增加Looper.prepare();

ThreadManager.getInstance().createLongPool().execute(new Runnable(){

            @Override
            public void run() {
                //SystemClock.sleep(3000);
                Looper.prepare();
                Toast.makeText(UiUtils.getContext(), "正在下载"+name, Toast.LENGTH_SHORT).show();
                Looper.loop();// 进入loop中的循环,查看消息队列
                /*
                    getActivity().runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                    }
                });
                */
            }
        });

方法二:post 给主线程去处理

// if current thread is background thread
// post show-toast-runnable to main handler
// if current thread is background thread
// post show-toast-runnable to main handler

mainHandler.post(new Runnable() {

   @Override
   public void run() {
      if (toast == null) {
         toast = Toast.makeText(context, "",     Toast.LENGTH_SHORT);
  }
  toast.setText(msg);
  toast.setDuration(Toast.LENGTH_SHORT);
  toast.show();
   }
});

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值