我使用了HandlerThread,然后使用它的looper创建一个新的Handler,以便它可以在非UI线程上运行操作。在发布到处理程序的runnable中,我添加了要显示的Toast消息。我预计会导致问题,因为您无法从非UI线程触摸UI组件,但它仍然有效,并且仍然显示Toast。任何人都可以解释为什么从非UI线程显示toast?
//Inside a Fragment class
private Handler handler;
private HandlerThread mHandlerThread = null;
public void startHandlerThread() {
mHandlerThread = new HandlerThread("HandlerThread");
mHandlerThread.start();
handler = new Handler(mHandlerThread.getLooper());
}
private Runnable submitRunnable = new Runnable() {
@Override
public void run() {
//do some long running operations here
//Thread.sleep(2000);
//Check whether currentLooper is the Main thread looper
boolean isUiThread = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
? Looper.getMainLooper().isCurrentThread()
: Thread.currentThread() == Looper.getMainLooper().getThread();
if (isUiThread) {
// You are on the UI thread
Log.d("Thread", "Main thread");
} else {
// You are on the non-UI thread
Log.d("Thread", "Not Main thread"); //This will be printed
}
Toast.makeText(getContext(), "toast is shown", Toast.LENGTH_SHORT).show();
}
};
submitButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handler.post(submitRunnable);
}
});
我检查了Toast.java,看到looper用Looper.myLooper()初始化自己。
if (looper == null) {
// Use Looper.myLooper() if looper is not specified.
looper = Looper.myLooper();
}
来自doc:
myLooper(): Return the Looper object associated with the current thread.
而currentThread是HandlerThread,而不是主线程。因此,我无法理解如何从非UI线程显示toast,或者如果它是一个简单的东西,我很想看到。
为了显示Toast,您使用getContext()
作为上下文。
getContext()
- 返回视图当前运行的上下文。通常是当前活动的Activity。
当您使用片段时,它将采用片段将驻留在活动中的活动上下文。
这就是Toast显示的原因。