태그 보관물: android-toast

android-toast

Looper.prepare ()를 호출하지 않은 스레드 내에서 핸들러를 작성할 수 없습니다. : java.lang.RuntimeException: Can’t create handler inside thread that

다음 예외는 무엇을 의미합니까? 어떻게 고칠 수 있습니까?

이것은 코드입니다.

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.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();
}

다른 옵션:

AsyncTask를 사용할 수 있습니다백그라운드에서 실행되는 대부분의 작업에 잘 작동 . 진행 상황과 완료 시점을 표시하기 위해 호출 할 수있는 후크가 있습니다.

당신은 또한 사용할 수 있습니다 Activity.runOnUiThread () .


답변

Toast.makeText(...)UI 스레드에서 호출해야합니다 .

activity.runOnUiThread(new Runnable() {
  public void run() {
    Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
  }
});

이것은 다른 (중복) SO 답변 에서 복사하여 붙여 넣습니다 .


답변

업데이트-2016

가장 좋은 대안은 데이터를 처리하기 위해 RxAndroid(에 대한 특정 바인딩 RxJava)을 사용하는 것 P입니다 MVP.

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

————————————————– ————————————————– ——————————

나는 내가 조금 늦었다는 것을 알고 있지만 여기에 간다. 안드로이드는 기본적으로 UI 스레드백그라운드 스레드의 두 가지 스레드 유형에서 작동 합니다 . 안드로이드 문서에 따르면-

이 문제를 해결하기 위해 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();

자벌레

스레드에 대한 메시지 루프를 실행하는 데 사용되는 클래스입니다. 스레드에는 기본적으로 메시지 루프가 없습니다. 하나를 만들려면 루프를 실행할 스레드에서 Preparing ()를 호출 한 다음 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
    }
}

매니저

핸들러를 사용하면 스레드의 MessageQueue와 연관된 Message 및 Runnable 객체를 보내고 처리 할 수 ​​있습니다.

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()Main / UI 스레드에서만 호출해야합니다. Looper.getMainLooper ()는 이를 달성하는 데 도움이됩니다.

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
    }
});

이 방법의 장점은 Activity 또는 Context없이 사용할 수 있다는 것입니다.


답변

처리기 전에 준비되지 않은 Looper로 인해 runtimeException이 표시되면이를 시도하십시오.

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

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

답변

나는 같은 문제에 부딪쳤다.

private final class UIHandler extends Handler
{
    public static final int DISPLAY_UI_TOAST = 0;
    public static final int DISPLAY_UI_DIALOG = 1;

    public UIHandler(Looper looper)
    {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg)
    {
        switch(msg.what)
        {
        case UIHandler.DISPLAY_UI_TOAST:
        {
            Context context = getApplicationContext();
            Toast t = Toast.makeText(context, (String)msg.obj, Toast.LENGTH_LONG);
            t.show();
        }
        case UIHandler.DISPLAY_UI_DIALOG:
            //TBD
        default:
            break;
        }
    }
}

protected void handleUIRequest(String message)
{
    Message msg = uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST);
    msg.obj = message;
    uiHandler.sendMessage(msg);
}

UIHandler를 작성하려면 다음을 수행해야합니다.

    HandlerThread uiThread = new HandlerThread("UIHandler");
    uiThread.start();
    uiHandler = new UIHandler((HandlerThread) uiThread.getLooper());

도움이 되었기를 바랍니다.


답변

오류 이유 :

워커 스레드는 백그라운드 작업을 수행하기위한 것이며 runOnUiThread 와 같은 메서드를 호출하지 않으면 워커 스레드 내의 UI에 아무것도 표시 할 수 없습니다 . runOnUiThread를 호출하지 않고 UI 스레드에 아무 것도 표시하려고하면java.lang.RuntimeException .

따라서 작업자 스레드에서 activity전화 Toast.makeText()를 거는 경우 다음을 수행하십시오.

runOnUiThread(new Runnable()
{
   public void run()
   {
      Toast toast = Toast.makeText(getApplicationContext(), "Something", Toast.LENGTH_SHORT).show();
   }
}); 

위의 코드는 Toast 메시지를 메소드 UI thread내부에서 호출하기 때문에 표시합니다 runOnUiThread. 더 이상은 없습니다 java.lang.RuntimeException.