I have an Activity, and in that I have a class.
text=new Dynamictext(...); text.setText("txt");
in my DynamicText java I have this code:
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) { } }
I get:
ERROR/AndroidRuntime(5176): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
How can I handle this error?
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.os.Looper. Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Looper , Handler , and HandlerThread are the Android's way of solving the problems of asynchronous programming. They are not old school, but a neat structure on which a complex android framework is built.
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue . Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler it is bound to a Looper .
User Interface Thread or UI-Thread in Android is a Thread element responsible for updating the layout elements of the application implicitly or explicitly. This means, to update an element or change its attributes in the application layout ie the front-end of the application, one can make use of the UI-Thread.
The error is self-explanatory... doInBackground()
runs on a background thread which, since it is not intended to loop, is not connected to a Looper
.
You most likely don't want to directly instantiate a Handler at all... whatever data your doInBackground()
implementation returns will be passed to onPostExecute()
which runs on the UI thread.
mActivity = ThisActivity.this; mActivity.runOnUiThread(new Runnable() { public void run() { new asyncCreateText().execute(); } });
ADDED FOLLOWING THE STACKTRACE APPEARING IN QUESTION:
Looks like you're trying to start an AsyncTask
from a GL rendering thread... don't do that cos they won't ever Looper.loop()
either. AsyncTasks are really designed to be run from the UI thread only.
The least disruptive fix would probably be to call Activity.runOnUiThread()
with a Runnable
that kicks off your AsyncTask
.
All the answers above are correct, but I think this is the easiest example possible:
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(); } }
What this does is update a progress bar in the UI thread from a completely different thread passed through the post() method of the handler declared in the activity.
Hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With