Mam aktywność, w której mam zajęcia.
text=new Dynamictext(...);
text.setText("txt");
w mojej java DynamicText mam ten kod:
public void setText(String text) {
this.text=text;
new asyncCreateText().execute();
//this.createText(text);
}
//private Handler handler = new Handler();
private class asyncCreateText extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... unused) {
return null;
}
@Override
protected void onPostExecute(Void unused) {
}
}
Dostaję:
BŁĄD / AndroidRuntime (5176): spowodowane przez: java.lang.RuntimeException: nie można utworzyć modułu obsługi wewnątrz wątku, który nie wywołał Looper.prepare ()
Jak mogę sobie poradzić z tym błędem?
ERROR/AndroidRuntime(5370): java.lang.ExceptionInInitializerError
ERROR/AndroidRuntime(5370): at com.l.start.DynamicText.setText(DynamicText.java:125)
ERROR/AndroidRuntime(5370): at com.l.start.OpenGLRenderer.initfonts(OpenGLRenderer.java:168)
ERROR/AndroidRuntime(5370): at com.l.start.OpenGLRenderer.init(OpenGLRenderer.java:119)
ERROR/AndroidRuntime(5370): at com.l.start.OpenGLRenderer.onSurfaceChanged(OpenGLRenderer.java:90)
ERROR/AndroidRuntime(5370): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1120)
ERROR/AndroidRuntime(5370): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)
ERROR/AndroidRuntime(5370): Caused by: java.lang.RuntimeException:
Can't create handler inside thread that has not called Looper.prepare()
ERROR/AndroidRuntime(5370): at android.os.Handler.<init>(Handler.java:121)
ERROR/AndroidRuntime(5370): at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370): at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370): at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
ERROR/AndroidRuntime(5370): ... 6 more
android
runtimeexception
lacas
źródło
źródło
Odpowiedzi:
Błąd jest oczywisty ...
doInBackground()
działa w wątku w tle, który, ponieważ nie jest przeznaczony do zapętlenia, nie jest podłączony doLooper
.Najprawdopodobniej w ogóle nie chcesz bezpośrednio tworzyć instancji programu obsługi ... wszelkie dane zwrócone przez Twoją
doInBackground()
implementację zostaną przekazane,onPostExecute()
które działają w wątku interfejsu użytkownika.mActivity = ThisActivity.this; mActivity.runOnUiThread(new Runnable() { public void run() { new asyncCreateText().execute(); } });
DODANO WEDŁUG ŚLADU STOSU POJAWIAJĄCEGO SIĘ W PYTANIU:
Wygląda na to, że próbujesz rozpocząć
AsyncTask
od wątku renderującego GL ... nie rób tego, bo oni też nigdy nie będąLooper.loop()
. AsyncTasks są tak naprawdę zaprojektowane do uruchamiania tylko z wątku interfejsu użytkownika.Najmniej uciążliwą poprawką byłoby prawdopodobnie wezwanie
Activity.runOnUiThread()
osoby,Runnable
która uruchomi TwójAsyncTask
.źródło
Wszystkie powyższe odpowiedzi są poprawne, ale myślę, że jest to najprostszy możliwy przykład:
public class ExampleActivity extends Activity { private Handler handler; private ProgressBar progress; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); progress = (ProgressBar) findViewById(R.id.progressBar1); handler = new Handler(); } public void clickAButton(View view) { // Do something that takes a while Runnable runnable = new Runnable() { @Override public void run() { handler.post(new Runnable() { // This thread runs in the UI @Override public void run() { progress.setProgress("anything"); // Update the UI } }); } }; new Thread(runnable).start(); } }
To powoduje aktualizację paska postępu w wątku interfejsu użytkownika z zupełnie innego wątku przekazanego przez metodę post () procedury obsługi zadeklarowanej w działaniu.
Mam nadzieję, że to pomoże!
źródło
W ten sposób tworzysz procedurę obsługi w wątku w tle
private void createHandler() { Thread thread = new Thread() { public void run() { Looper.prepare(); final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { // Do Work handler.removeCallbacks(this); Looper.myLooper().quit(); } }, 2000); Looper.loop(); } }; thread.start(); }
źródło
removeCallbacks
iquit
kiedyWork
zostanie to zrobione, ale nie nastąpi opóźnienie. Ponieważ praca może trwać dłużej niż wstępnie zdefiniowane opóźnienie.Activity.runOnUiThread()
nie działa dla mnie. Omówiłem ten problem, tworząc zwykły wątek w ten sposób:public class PullTasksThread extends Thread { public void run () { Log.d(Prefs.TAG, "Thread run..."); } }
i wywołując go z aktualizacji GL w ten sposób:
new PullTasksThread().start();
źródło
Spróbuj uruchomić swoje zadanie jako zadanie z poziomu wątku interfejsu użytkownika. Zmierzyłem się z tym problemem, kiedy nie robiłem tego samego!
źródło
Spróbuj tego
Handler mHandler = new Handler(Looper.getMainLooper()); mHandler.post(new Runnable() { @Override public void run() { //your code here that talks with the UI level widgets/ try to access the UI //elements from this block because this piece of snippet will run in the UI/MainThread. } });
źródło