在子线程创建并显示一个Toast
来源:互联网 发布:最终幻想模型制作软件 编辑:程序博客网 时间:2024/05/22 23:04
一般我们要显示一个Toast的时候,默认情况下都是在主线程中有如下做法:
Toast.makeText(mContext, "我是一个Toast", Toast.LENGTH_LONG).show();
我们看看makeText里面干了什么:
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; }
默认情况下,会从系统xml文件中获得一个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,其中有个成员变量是handler,在创建TN对象的时候就初始化了:
final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { IBinder token = (IBinder) msg.obj; handleShow(token); } };
我们知道初始化一个Handler对象是必须要有looper对象的,如下:
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; }
它会去得到当前线程的looper对象,如果得不到就会报异常。
一般情况下我们是在主线程创建的Toast,主线程默认在ActivityThread的main方法中就执行了looper的初始化,所以不会报错。
所以我们如果想在子线程中创建一个Toast对象,那么就必须先创建一个Looper对象。如下:
new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); Looper.prepare(); Toast.makeText(ThreadTostActivity.this, "我是一个线程里的Toast", Toast.LENGTH_LONG).show(); Looper.loop(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start();
使用Looper.prepare方法在当前线程创建了looper,然后makeText的时候,会创建handler,该handler自然就跟当前线程里的looper对象关联上了。于是就能显示出来了。
相似的,dialog也可以在线程中执行,其内部也是有个成员变量handler,在定义的时候就已经初始化了。
另外使用dialog需要注意的就是必须依附于activity,如果要在service中使用dialog则要另外设置:
http://blog.csdn.net/huxueyan521/article/details/8954844
原因如下:
http://www.jianshu.com/p/413ec659500a
大致就是因为在创建dialog的时候,我们传进来的context的区别,传进来activity的context时parentWindow不会为空,但传进来其他类型的context,则会导致parentWindow为空,一旦为空,接下来在添加到window的时候就报异常了。
另附,activity中的context和application和service的context的区别:
- 在子线程创建并显示一个Toast
- 自定义可以在子线程显示的Toast,并自定义显示时长和位置
- Android-在子线程中显示Toast和Dialog
- 在子线程中Toast
- 在子线程中Toast
- Android在子线程使用Toast
- 在子线程中弹出Toast
- 为啥Toast在子线程报错
- 在子线程里面使用Toast
- 如何在子线程弹Toast
- Looper.prepare(),Looper.loop()和在子线程中显示Toast
- Android在子线程中显示Toast实现与源码分析
- Toast不显示的原因和在子线程中使用方法以及Looper类详细解析
- [转]在其他线程中显示Toast
- 在非UI线程中显示Toast
- Android 之 子线程中创建子线程以及子线程中toast 问题
- Android Toast工具类 解决Toast重复显示,Toast一直显示,在线程中可用
- 子线程的Toast怎么显示不出来问题解决
- 【KF8V111控制器】I/O配置
- 美团Codem编程比赛资格赛:数码
- CSS 样式(二)
- 对软件开发感到惊讶的共识
- 入门Webpack,看这篇就够了
- 在子线程创建并显示一个Toast
- 三种经典iPhone上网络抓包方法详解
- databinding使用include
- 程序员为什么要写周报?
- 弃农药坑回归编程之路
- 【Java并发编程】Thread方式创建线程
- Android的数据存储方式之一——SharedPreferences
- iOS 录制屏幕
- 字节大小端