Android java.lang.RuntimeException:Can';t在未调用Looper.prepare()的线程内创建处理程序;
我有一个运行线程的Android应用程序。我想用祝酒词来表达我的祝酒词 当我这样做时,我得到以下异常: Logcat跟踪:Android java.lang.RuntimeException:Can';t在未调用Looper.prepare()的线程内创建处理程序;,android,multithreading,toast,Android,Multithreading,Toast,我有一个运行线程的Android应用程序。我想用祝酒词来表达我的祝酒词 当我这样做时,我得到以下异常: Logcat跟踪: FATAL EXCEPTION: Timer-0 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() at android.os.Handler.<init>(Handler.java:121)
FATAL EXCEPTION: Timer-0
java.lang.RuntimeException: Can't create handler inside thread that has not
called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.widget.Toast$TN.<init>(Toast.java:322)
at android.widget.Toast.<init>(Toast.java:91)
at android.widget.Toast.makeText(Toast.java:238)
致命异常:计时器-0
java.lang.RuntimeException:无法在尚未创建的线程内创建处理程序
调用Looper.prepare()
android.os.Handler.(Handler.java:121)
在android.widget.Toast$TN.(Toast.java:322)
在android.widget.Toast.(Toast.java:91)
位于android.widget.Toast.makeText(Toast.java:238)
是否有办法将Toast消息从线程推送到用户界面?来自:
此外,Android UI工具包不是线程安全的<那么,你呢
不能从工作线程操作UI-您必须完成所有操作
从UI线程对用户界面进行操作。因此,
Android的单线程模型有两条规则:
strings.xml中
<string name="idleness_toast">"You are getting late do it fast"</string>
不要使用AlertDialog,做出选择。AlertDialog和Toast是两个不同的东西。我遇到这个异常是因为我试图从后台线程中弹出Toast。
Toast需要一个活动来推送到用户界面,而线程没有这个活动。
因此,一种解决方法是给线程一个指向父活动的链接,并为此干杯
将此代码放在要发送Toast消息的线程中:
parent.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(parent.getBaseContext(), "Hello", Toast.LENGTH_LONG).show();
}
});
在创建此线程的后台线程中保留指向父活动的链接。在线程类中使用父变量:
private static YourActivity parent;
创建线程时,将父活动作为参数通过构造函数传递,如下所示:
public YourBackgroundThread(YourActivity parent) {
this.parent = parent;
}
现在,后台线程可以将Toast消息推送到屏幕上。以下是我一直在做的事情:
public void displayError(final String errorText) {
Runnable doDisplayError = new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), errorText, Toast.LENGTH_LONG).show();
}
};
messageHandler.post(doDisplayError);
}
这应该允许从任一线程调用该方法
其中messageHandler在活动中声明为
Handler messageHandler = new Handler();
Android基本上使用两种线程类型,即UI线程和后台线程。根据android文档-
不要从UI线程外部访问Android UI toolkit要解决此问题,Android提供了几种从其他线程访问UI线程的方法。下面列出了一些可以提供帮助的方法:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
现在有各种各样的方法来解决这个问题。我将通过代码示例来解释它
runOnUiThread
new Thread()
{
public void run()
{
myactivity.this.runOnUiThread(new runnable()
{
public void run()
{
//Do your UI operations like dialog opening or Toast here
}
});
}
}.start();
活套
类用于为线程运行消息循环。默认情况下,线程没有与之关联的消息循环;要创建一个,请在运行循环的线程中调用prepare(),然后调用loop(),让它处理消息,直到循环停止
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
异步任务
AsyncTask允许您在用户界面上执行异步工作。它在工作线程中执行阻塞操作,然后在UI线程上发布结果,而不需要您自己处理线程和/或处理程序
public void onClick(View v) {
new CustomTask().execute((Void[])null);
}
private class CustomTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... param) {
//Do some work
return null;
}
protected void onPostExecute(Void param) {
//Print Toast or open dialog
}
}
您只需使用BeginInvokeMainThread()。它调用设备主(UI)线程上的操作
它很简单,非常适合我
编辑:如果您使用的是C#Xamarin,则可以使用
这对我来说很有效我从以下代码中获得了一个错误:
BluetoothLeScanner bluetoothLeScanner = getBluetoothLeScanner();
if (BluetoothAdapter.STATE_ON == getBluetoothAdapter().getState() && null != bluetoothLeScanner) {
// ...
} else {
Logger.debug(TAG, "BluetoothAdapter isn't on so will attempting to turn on and will retry starting scanning in a few seconds");
getBluetoothAdapter().enable();
(new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
startScanningBluetooth();
}
}, 5000);
}
服务崩溃:
2019-11-21 11:49:45.550 729-763/? D/BluetoothManagerService: MESSAGE_ENABLE(0): mBluetooth = null
--------- beginning of crash
2019-11-21 11:49:45.556 8629-8856/com.locuslabs.android.sdk E/AndroidRuntime: FATAL EXCEPTION: Timer-1
Process: com.locuslabs.android.sdk, PID: 8629
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:203)
at android.os.Handler.<init>(Handler.java:117)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService.startScanningBluetoothAndBroadcastAnyBeaconsFoundAndUpdatePersistentNotification(BeaconScannerJobService.java:120)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService.access$500(BeaconScannerJobService.java:36)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService$2$1.run(BeaconScannerJobService.java:96)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
现在代码不再抛出运行时异常
。在重写的public void inactivitydetected()中,我使用了toast函数IdleTimer=new IdleTimer(5000,new IIdleCallback(){@Override public void inactivitydetected(){AlertDialog.Builder alertDialogBuilder=new AlertDialog.Builder(getApplicationContext());Toast.makeText(null,“你要迟到了,快做吧…”),Toast.LENGTH_LONG.show();}});if(idleTimer.checkIsTimerRunning()){idleTimer.stopidleimer();}idleTimer.startidleimer();我只是希望我的idleTimer线程中要在我的主ui上显示的东西应该是…抱歉,我把所有的东西都弄乱了代码是这样的idleTimer=new idleTimer(5000,new IIdleCallback(){@Override public void inactivityDetected(){Toast.makeText(getApplicationContext(),“你要迟到了,快点做…”,Toast.LENGTH_LONG.show();});if(idleTimer.checkIsTimerRunning()){idleTimer.stopidleimer();}idleTimer.startidleimer();我如何在该活动中调用方法(我正在使用此代码制作祝酒词)?请不要将后续问题作为评论发布。评论用于讨论顶部的问题,以及我的答案是否适合回答该问题。我们遵守规则很重要。遵守规则的每个人都是保持堆栈溢出的原因很好,并防止它变成像yahoo answers那样的马戏团。对于Xamarin Android,Activity.rununuithread(()=>Toast.MakeText(this.Activity.ApplicationContext,“Message Text”,ToastLength.Short)。Show());这不是Xamarin特有的API,与Android本机(没有Xamarin标记)问题无关吗?是的,你说得对。很抱歉,我没有注意到。但是使用Xamarin查找错误解决方案的用户正在登录此页面。因此,我将帖子放在这里,只是对Xamarin进行了精确说明。“设备”来自哪个程序集/命名空间?@MJ33它来自Xamarin.Forms
Device.BeginInvokeOnMainThread(() => { displayToast("text to display"); });
runOnUiThread(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(), "Status = " + message.getBody() , Toast.LENGTH_LONG).show();
}
});
BluetoothLeScanner bluetoothLeScanner = getBluetoothLeScanner();
if (BluetoothAdapter.STATE_ON == getBluetoothAdapter().getState() && null != bluetoothLeScanner) {
// ...
} else {
Logger.debug(TAG, "BluetoothAdapter isn't on so will attempting to turn on and will retry starting scanning in a few seconds");
getBluetoothAdapter().enable();
(new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
startScanningBluetooth();
}
}, 5000);
}
2019-11-21 11:49:45.550 729-763/? D/BluetoothManagerService: MESSAGE_ENABLE(0): mBluetooth = null
--------- beginning of crash
2019-11-21 11:49:45.556 8629-8856/com.locuslabs.android.sdk E/AndroidRuntime: FATAL EXCEPTION: Timer-1
Process: com.locuslabs.android.sdk, PID: 8629
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:203)
at android.os.Handler.<init>(Handler.java:117)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService.startScanningBluetoothAndBroadcastAnyBeaconsFoundAndUpdatePersistentNotification(BeaconScannerJobService.java:120)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService.access$500(BeaconScannerJobService.java:36)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService$2$1.run(BeaconScannerJobService.java:96)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
(new Timer()).schedule(new TimerTask() {
@Override
public void run() {
startScanningBluetooth();
}
}, 5000);