Erro Android: Only one looper may be created per thread

6 respostas
eliangela

Olá pessoal!

Segue abaixo minha classe para trabalhar com Dialogs no Android:
package br.com.tdta.service.view;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Looper;

public class MessageDialog {

	public static void showOkDialog(Activity context, String msg) {
		Looper.prepare();
		final Looper myLooper = Looper.myLooper();

		final AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setMessage(msg).setNeutralButton("OK", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				myLooper.quit();
				arg0.dismiss();
			}
		});

		builder.create().show();
		Looper.loop();
	}

	public static void showOkDialog(Activity context, String msg, final OnClickListener listener) {
		Looper.prepare();
		final Looper myLooper = Looper.myLooper();

		final AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setMessage(msg).setNeutralButton("OK", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				listener.onClick(arg0, arg1);
				myLooper.quit();
				arg0.dismiss();
			}
		});

		builder.create().show();
		Looper.loop();
	}

	public static void showSimNaoDialog(Activity context, String msg, final OnClickListener listenerSim) {
		Looper.prepare();
		final Looper myLooper = Looper.myLooper();

		AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setMessage(msg).setPositiveButton("Sim", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				listenerSim.onClick(arg0, arg1);
				myLooper.quit();
				arg0.dismiss();
			}
		}).setNegativeButton("Não", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				myLooper.quit();
				arg0.dismiss();
			}
		});
		builder.create().show();
		Looper.loop();
	}
}
O problema é que, se eu chamo uma Dialog na minha activity, e depois chamo outra, com outra msg, dá o seguinte erro:
FATAL EXCEPTION: Thread-8
java.lang.RuntimeException: Only one Looper may be created per thread
    at android.os.Looper.prepare
    at br.com.tdta.service.view.MessageDialog.showOkDialog
    at br.com.tdta.service.view.AtualizaDados.atualizaDados
    at br.com.tdta.service.view.AtualizaDados.access$000
    at br.com.tdta.service.view.AtualizaDados$1.run
    at java.lang.Thread.run

Se eu tirar o Looper.prepare(), cai em outra exception, dizendo que TEM que ter esse Looper.prepare(). Agora não sei mais o que fazer.

6 Respostas

Marky.Vasconcelos

Não tem outra solução sem o Looper?

Marky.Vasconcelos

Aliás, olhando na documentação da classe Looper:
http://developer.android.com/reference/android/os/Looper.html

Ele só usa Looper.prepare() e Looper.loop() depois.

eliangela

Não consegui nenhuma solução sem o Looper…

Marky.Vasconcelos:
Aliás, olhando na documentação da classe Looper:
http://developer.android.com/reference/android/os/Looper.html

Ele só usa Looper.prepare() e Looper.loop() depois.


Sobre a documentação:

public static final void prepare ()

Initialize the current thread as a looper. This gives you a chance to create handlers that then reference this looper, before actually starting the loop. Be sure to call loop() after calling this method, and end it by calling quit().

Na documentação do método prepare(), ele pede pra encerrar usando o método quit().
Vou tentar sem o quit() aqui…

eliangela

Marky.Vasconcelos:
Aliás, olhando na documentação da classe Looper:
http://developer.android.com/reference/android/os/Looper.html

Ele só usa Looper.prepare() e Looper.loop() depois.

testei aqui sem o quit(). Se eu não usa-lo, a aplicação fica numa espécie de loop infinito.

eliangela

Resolvi assim:

Apaguei aquela classe que mostrava as caixinhas de dialogo. Ao invés de ter uma classe estática, toda vez que eu preciso de um Dialog, eu faço isso:

Looper.prepare();
new AlertDialog.Builder(this).setMessage("Ocorreu um erro ao conectar no servidor").setNeutralButton("OK", new AlertDialog.OnClickListener() {

	public void onClick(DialogInterface arg0, int arg1) {
		Looper.myLooper().quit();
	}
}).create().show();
Looper.loop();

Caso dê o erro Only one looper may be created per thread, eu tiro os Looper, assim:

new AlertDialog.Builder(InformaIP.this).setMessage("Ocorreu um erro ao conectar no servidor").setNeutralButton("OK", new AlertDialog.OnClickListener() {

	public void onClick(DialogInterface arg0, int arg1) {
		//
	}
}).create().show();

É triste, mas foi com essa POG que eu estou seguindo com o projeto.
Por favor, caso alguém tenha uma solução melhor, posta aqui.

eliangela
Fiz a POG numa classe separada, usando uns IF....
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Looper;

/**
 *
 * @author eliangela
 */
public class MessageDialog {

	private static boolean erro = false;

	public static void showOkDialog(Activity act, String msg) {
		try {
			Looper.prepare();
		} catch (Exception e) {
			erro = true;
		}
		new AlertDialog.Builder(act).setMessage(msg).
				setNeutralButton("OK", new AlertDialog.OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				if (!erro) {
					Looper.myLooper().quit();
				}

				erro = false;
			}
		}).create().show();
		if (!erro) {
			Looper.loop();
		}
	}

	public static void showOkDialog(Activity act, String msg, final OnClickListener listener) {
		try {
			Looper.prepare();
		} catch (Exception e) {
			erro = true;
		}
		new AlertDialog.Builder(act).setMessage(msg).
				setNeutralButton("OK", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				listener.onClick(arg0, arg1);
				if (!erro) {
					Looper.myLooper().quit();
				}

				erro = false;
			}
		}).create().show();
		if (!erro) {
			Looper.loop();
		}
	}

	public static void showSimNaoDialog(Activity act, String msg, final OnClickListener listenerSim) {
		try {
			Looper.prepare();
		} catch (Exception e) {
			erro = true;
		}
		new AlertDialog.Builder(act).setMessage(msg).
				setPositiveButton("Sim", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				listenerSim.onClick(arg0, arg1);
				if (!erro) {
					Looper.myLooper().quit();
				}

				erro = false;
			}
		}).setNegativeButton("Não", new OnClickListener() {

			public void onClick(DialogInterface arg0, int arg1) {
				if (!erro) {
					Looper.myLooper().quit();
				}

				erro = false;
			}
		}).create().show();
		if (!erro) {
			Looper.loop();
		}
	}
}

Recaptulando: se alguem tiver uma solução melhor, por fv, poste.

Criado 31 de agosto de 2011
Ultima resposta 1 de set. de 2011
Respostas 6
Participantes 2