Android java.lang.RuntimeException:Can';t在未调用Looper.prepare()的线程内创建处理程序;

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)

我有一个运行线程的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)
 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的单线程模型有两条规则:

  • 不要阻塞UI线程
  • 不要从UI线程外部访问Android UI工具包
  • 您必须检测工作线程中的空闲状态,并在主线程中显示祝酒词

    如果你想得到更详细的答案,请发一些代码

    代码发布后:

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