在工作线程中创建Toast,代码如下:
private void showToast() {
new Thread() {
public void run() {
Looper.prepare();
Toast.makeText(ActivityA.this, "来自工作线程",
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
}
如果不加Looper.prepare();则会出现以下异常:
java.lang.RuntimeException: Can't create handler inside thread that has not called
Looper.prepare()
所以 在工作线程中创建Toast 须创建Looper对象。Looper.prepare();会创建当前线程的Looper对象和对应的MessageQueue(消息队列)
请参看Toast.java源码。
Toast.java 包含 这句代码:final Handler mHandler = new Handler();
mHandler是Toast的一个final类型的成员变量,在Handler的构造方法中有如下代码:
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called
Looper.prepare()");
}
创建了Toast对象后,调用show()方法,把mShow这个Runnable添加到工作线程的消息队列中,
消息队列是在创建Looper对象的时候创建好的。
如代码:
final Runnable mShow = new Runnable() {
public void run() {
handleShow();
}
};
public void show() {
if (localLOGV) Log.v(TAG, "SHOW: " + this);
mHandler.post(mShow);
}
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
*/
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
此时调用Looper.loop(),从消息队列中取出消息,并执行。
主要源码:
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
......
msg.target.dispatchMessage(msg);
......
msg.recycle();
}
}
}
此时会调用:mShow的handleShow();
源码:
public void handleShow() {
if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+ " mNextView=" + mNextView);
if (mView != mNextView) {
// remove the old view if necessary
handleHide();
mView = mNextView;
mWM = WindowManagerImpl.getDefault();
final int gravity = mGravity;
mParams.gravity = gravity;
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) ==
Gravity.FILL_HORIZONTAL) {
mParams.horizontalWeight = 1.0f;
}
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) ==
Gravity.FILL_VERTICAL) {
mParams.verticalWeight = 1.0f;
}
mParams.x = mX;
mParams.y = mY;
mParams.verticalMargin = mVerticalMargin;
mParams.horizontalMargin = mHorizontalMargin;
if (mView.getParent() != null) {
if (localLOGV) Log.v(
TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
}
if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
mWM.addView(mView, mParams);
}
}
mWM.addView(mView, mParams);把Toast对应的view添加到当前Window中。
举一反三:
基于以上原理,可以实现这样的效果,拖动GridView里的ImageView元素,改变元素在GridView的位置。
分享到:
相关推荐
在 run 方法中,我们首先将要显示的信息设置到 TextView 中,然后使用 Toast.makeText 方法创建一个 Toast 对象,并使用 show 方法将其显示出来。 需要注意的是,在在线程中使用 Toast 时,需要使用主Activity 的 ...
接下来,我们将讨论如何在Qt中创建toast控件。这通常涉及到以下步骤: 1. **定义Toast类**:创建一个新的Qt Widget类,命名为`Toast`,继承自`QWidget`。在这个类中,我们需要设置控件的基本属性,如大小、颜色、...
如果需要在Toast中显示图片,可以通过获取Toast的布局视图,并向其中添加ImageView。首先获取Toast的视图,然后创建ImageView并设置图片资源,最后将ImageView添加到Toast的布局中。以下代码展示了如何在Toast中添加...
在主线程中频繁使用`Toast`可能会阻塞UI,因此建议在子线程中创建并显示`Toast`,并通过`runOnUiThread`确保在UI线程执行: ```java context.runOnUiThread(new Runnable() { @Override public void run() { ...
在主线程中创建`Toast`是安全的,但在其他线程中则需要处理。你可以使用`runOnUiThread`或`Handler`确保`Toast`在UI线程中显示: ```java new Thread(new Runnable() { @Override public void run() { // 在子...
7. 注意事项:`Toast`不是线程安全的,应在UI线程中创建和显示。此外,`Toast`是全局的,同一时间只能显示一个`Toast`。 通过这个“Toast演示”,初学者不仅可以了解`Toast`的基本用法,还可以学习到如何在实际项目...
3. **检查线程**:在多线程环境中,确保`Toast`的创建和显示都在主线程进行,因为`Toast`必须在UI线程中显示。 4. **避免循环调用**:如果`Toast`在循环或定时任务中使用,可以设置一个标志位来控制是否需要显示,...
开发者可能通过创建一个新的`Thread`,在该线程中执行任务,并使用`Handler`将完成任务的消息传回主线程,以便在主线程中调用`Toast`显示信息。 总之,理解并熟练运用`Service`、`Thread`、`Toast`和`Handler`是...
值得注意的是,`Toast`是线程安全的,可以在任何线程中创建和显示,但在主线程中调用`show()`方法以确保UI更新的正常进行。此外,`Toast`的生命周期较短,一旦显示完毕,它就会自动消失,无需手动清理。 在实际项目...
然而,Service通常运行在自己的工作线程中,这意味着在Service中直接使用Toast可能会导致`android.view.ViewRootImpl$CalledFromWrongThreadException`异常。为了解决这个问题,有以下两种常见方法: 1. 使用`...
在本文中,我们将深入探讨如何在Qt环境中实现一个仿安卓Toast效果的功能,这将帮助开发者在他们的Qt应用中创建类似Android系统中短暂显示信息的组件。这个功能是跨平台的,可以在Windows和Linux(如Ubuntu)等操作...
为了实现上述功能,开发者需要对Android的生命周期有深入理解,熟悉线程管理,了解如何在主线程和工作线程之间进行通信。此外,还需要掌握布局设计和UI组件的使用,以便创建美观且易于使用的`Dialog`和`Toast`。 在...
由于`Toast`不是线程安全的,因此应该确保在主线程中创建和显示`Toast`。在非主线程中,可以使用`runOnUiThread()`: ```java context.runOnUiThread(new Runnable() { @Override public void run() { Toast....
默认情况下,`Toast`在主线程中显示,但在某些场景下,你可能需要在子线程中使用`Toast`。由于Android UI操作必须在主线程进行,因此你需要使用`runOnUiThread()`方法。例如: ```java new Thread(() -> { try {...
如果在主线程以外的地方显示`Toast`,需要确保在UI线程中执行,可以使用`runOnUiThread()`: ```java context.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(context, "异步...
6. 处理多线程问题:如果`Toast`在非主线程中显示,需要确保在正确的线程中进行显示操作,通常使用`runOnUiThread`或`Handler`来处理。 7. 销毁`Toast`:当不再需要`Toast`时,可以调用`cancel()`方法来取消显示,...
如果需要在其他线程中使用`Toast`,可以使用`runOnUiThread()`或`Handler`来确保操作在主线程执行。 9. **适配不同设备和屏幕尺寸** - 考虑到不同设备的屏幕尺寸和分辨率,应适当调整`Toast`的大小和位置,使其在...
在多线程环境中,确保在主线程中创建和显示`Toast`,因为它是不线程安全的。可以使用`runOnUiThread()`或`Handler`来保证这一点。 6. **全局`Toast`** 为了在多个地方方便地使用`Toast`,你可以创建一个全局的`...
在大型项目中,为了统一管理`Toast`的显示,可以创建一个全局的`Toast`工具类,提供静态方法来显示`Toast`,这样可以在任何地方方便地调用,同时便于后期维护和修改。 8. **线程安全** 考虑到`Toast`可能会在多个...