下面的异常是什么意思;我该怎么解决呢?

这是代码:

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);

这是例外:

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.<init>(Toast.java:68)
     at android.widget.Toast.makeText(Toast.java:231)

当前回答

Toast, alertdialog需要在UI线程上运行,你可以使用Asynctask在android开发中正确使用它们。但有些情况下,我们需要自定义超时,所以我们使用线程,但在线程中,我们不能使用Toast, alertdialog,就像我们在AsyncTask中使用的那样。我们需要单独的Handler来处理弹出这些。

public void onSigned() {
    Thread thread = new Thread(){
        @Override
        public void run() {
            try{
                sleep(3000);
                Message message = new Message();
                message.what = 2;
                handler.sendMessage(message);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    };
    thread.start();
}

在上面的例子中,我想睡我的线程在3秒后,我想显示一个吐司消息,在你的主线程实现处理程序。

handler = new Handler() {
       public void handleMessage(Message msg) {
           switch(msg.what){
              case 1:
              Toast.makeText(getActivity(),"cool",Toast.LENGTH_SHORT).show();
              break;
           }
           super.handleMessage(msg);
       }
};

我在这里使用了switch case,因为如果你需要以相同的方式显示不同的消息,你可以在Handler类中使用switch case…希望这对你有所帮助

其他回答

Toast, alertdialog需要在UI线程上运行,你可以使用Asynctask在android开发中正确使用它们。但有些情况下,我们需要自定义超时,所以我们使用线程,但在线程中,我们不能使用Toast, alertdialog,就像我们在AsyncTask中使用的那样。我们需要单独的Handler来处理弹出这些。

public void onSigned() {
    Thread thread = new Thread(){
        @Override
        public void run() {
            try{
                sleep(3000);
                Message message = new Message();
                message.what = 2;
                handler.sendMessage(message);
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    };
    thread.start();
}

在上面的例子中,我想睡我的线程在3秒后,我想显示一个吐司消息,在你的主线程实现处理程序。

handler = new Handler() {
       public void handleMessage(Message msg) {
           switch(msg.what){
              case 1:
              Toast.makeText(getActivity(),"cool",Toast.LENGTH_SHORT).show();
              break;
           }
           super.handleMessage(msg);
       }
};

我在这里使用了switch case,因为如果你需要以相同的方式显示不同的消息,你可以在Handler类中使用switch case…希望这对你有所帮助

使用λ:

activity.runOnUiThread(() -> Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show());

更新- 2016

最好的替代方案是使用RxAndroid(针对RxJava的特定绑定)让MVP中的P负责数据。

首先从你现有的方法返回Observable。

private Observable<PojoObject> getObservableItems() {
    return Observable.create(subscriber -> {

        for (PojoObject pojoObject: pojoObjects) {
            subscriber.onNext(pojoObject);
        }
        subscriber.onCompleted();
    });
}

像这样使用这个Observable -

getObservableItems().
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Observer<PojoObject> () {
    @Override
    public void onCompleted() {
        // Print Toast on completion
    }

    @Override
    public void onError(Throwable e) {}

    @Override
    public void onNext(PojoObject pojoObject) {
        // Show Progress
    }
});
}

----------------------------------------------------------------------------------------------------------------------------------

我知道我来晚了一点,但我要开始了。 Android主要工作在两种线程类型上,即UI线程和后台线程。根据android文档-

不要从UI线程外部访问Android UI工具包来解决这个问题,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

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
    }
}

处理器允许您发送和处理Message和Runnable对象 与线程的messagqueuue相关联。

Message msg = new Message();


new Thread()
{
    public void run()
    {
        msg.arg1=1;
        handler.sendMessage(msg);
    }
}.start();



Handler handler = new Handler(new Handler.Callback() {

    @Override
    public boolean handleMessage(Message msg) {
        if(msg.arg1==1)
        {
            //Print Toast or open dialog        
        }
        return false;
    }
});

你从工作线程调用它。您需要在主线程中调用Toast.makeText()(以及处理UI的大多数其他函数)。例如,您可以使用处理程序。

在文档中查找与UI线程通信。简而言之:

// Set this up in the UI thread.

mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message message) {
        // This is where you do your work in the UI thread.
        // Your worker tells you in the message what to do.
    }
};

void workerThread() {
    // And this is how you call it from the worker thread:
    Message message = mHandler.obtainMessage(command, parameter);
    message.sendToTarget();
}

其他选项:

你可以使用Activity.runOnUiThread()。直截了当,如果你有一个活动:

@WorkerThread
void workerThread() {
    myActivity.runOnUiThread(() -> {
        // This is where your UI code goes.
    }
}

你也可以发布到主循环程序。如果你只有一个Context,这很有用。

@WorkerThread
void workerThread() {
    ContextCompat.getMainExecutor(context).execute(()  -> {
        // This is where your UI code goes.
    }
}

弃用:

你可以使用AsyncTask,它对大多数在后台运行的东西都很有效。它有钩子,你可以调用它来指示进度,以及什么时候完成。

它很方便,但如果使用不当,可能会泄漏上下文。它已被正式弃用,您不应该再使用它了。

尝试这个,当你看到runtimeException由于循环程序没有准备之前的处理程序。

Handler handler = new Handler(Looper.getMainLooper()); 

handler.postDelayed(new Runnable() {
  @Override
  public void run() {
  // Run your task here
  }
}, 1000 );