I understand what the CalledFromWrongThreadException exception means, but I cannot comprehend how the code I have written isn't executing on the uithread in this situation.
In my main activity I create a handler.
private final Handler handler = new AppHandler(this);
In the onCreateDialog method of the activity, I was using the constructor suggested by the android examples of timepicker dialogues. Since I was getting the CalledFromWrongThreadException in a way I didn't understand and wasn't reproducible on my devices or the emulator, I tried to pass a reference of my activity in to the create dialogue constructor.
So my code to create the dialog looks like this.
#Override
protected Dialog onCreateDialog(int id) {
final Calendar c = Calendar.getInstance();
switch (id) {
case TIME_DIALOG_ID:
return new TimePickerDialog(this, this, getHandler(),
mTimeSetListener, c.get(Calendar.HOUR_OF_DAY),
0, false);
The first instance of "this" gets used as a Context by the dialog, the second instance gets stored off as an Activity.
The dialog itself is the android sample code but I have been attempting to fix the threading problems I'm seeing.
Then inside of the dialog where I am having threading issues. I use the main activity and try to use its handler to execute the setTitle command as a runnable.
mainactivity.getHandler().post(new Runnable() {
public void run() {
setTitle(mDateFormat.format(mCalendar.getTime()));
}
});
Edit: Changing the code so that the attempt to run on the ui thread is using the method on the main activity instead of the handler produces the same results.
mainactivity.runOnUiThread(new Runnable() {
public void run() {
setTitle(mDateFormat.format(mCalendar.getTime()));
}
});
Here's a copy of a stacktrace:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:3214)
at android.view.ViewRoot.invalidateChild(ViewRoot.java:681)
at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:707)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
at android.view.View.invalidate(View.java:5418)
at android.widget.TextView.checkForRelayout(TextView.java:5750)
at android.widget.TextView.setText(TextView.java:2866)
at android.widget.TextView.setText(TextView.java:2727)
at android.widget.TextView.setText(TextView.java:2696)
at com.android.internal.app.AlertController.setTitle(AlertController.java:222)
at android.app.AlertDialog.setTitle(AlertDialog.java:100)
at com.testapp.TimePickerDialog$1.run(TimePickerDialog.java:159)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3691)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
at dalvik.system.NativeStart.main(Native Method
Also note that I use this same handler all over my app to successfully execute things on the UI thread.
Any suggestions on other approaches I might try or tips to debug this would be greatly appreciated.
Thanks!
Use
runOnUiThread(new Runnable() {
#Override
public void run() {
//UI CODES
}});
Edit
I think u should deal the DialogClass as innerclass for mainActivity,then just call runOnUiThread
Hope this may help you
In the end the issue is that I was calling showDialog() from a thread that was not the ui thread.
I figured out the issue when reading android dev blog on memory leaking and realized that I had passed a handle to the activity beyond where it should be.
I'm now calling showDialog() from inside of the runOnUiThread of the main activity as sonu pointed out and everything seems to be working.
Related
I am trying to use an SDK that seems to need to create a handler into my service.
A error message appeared saying that I can't create handler if the thread has not called Looper.prepare(), so I do call Looper.prepare() and this problem disappear.
However, this service need to start an activity after a while, and this Looper.prepare() seems to be messing with it, as the first UI function crash saying that it cannot be called from a non-ui thread.
I am a bit confused about why this is happening, and the research I made on thread and looper didn't help me. I get why we cannot create a handler if a looper does not exist on the thread, but not why creating a looper prevent me from using the ui thread afterward.
Below my code simplified :
public class MyService extends Service implement SDKCallback{
...
void callSDK(){
Looper.prepare();
SDK.run(); //Does thing I don't know about
}
#Override
SDKCallback(){
startActivity(new Intent(this, MyActivity.class);
}
}
You dont have to call Looper.prepare(). Try this code to create Handler,
new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message message) {
}
};
If you put Looper.prepare() in your worker thread, it will solve your first crash problem [the thread has not called Looper.prepare()]. But its not in UI thread, so you cant start next Activity.
What this above code does is, it creates the Handler in UI thread. So you can start next Activity.
Edit: Try this.
#Override
SDKCallback(){
new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message message) {
startActivity(new Intent(MyService.this, MyActivity.class));
}
};
}
I am currently developing an Android app where I need to perform a method inside a thread. I have the following code in order to create the thread and perform the
new Thread(new Runnable() {
#Override
public void run() {
new DownloadSync(getApplicationContext());
}
}).start();
When I try to run this code it displays the error message in the log cat:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.Prepare().
How can I fix this problem?
Use AsyncTask. Your situation is the reason for its existence. Also, read up on Painless Threading (which is mostly using AsyncTask).
The issue with your code is that something is trying to use a Handler internally in your new Thread, but nothing has told the Looper to prepare.
I had an earlier answer that was not very helpful - I've removed it and kept the relevant bit:
Make sure your DownLoadSync object only communicates with the main UI thread via a handler (if you want to avoid using an AsyncTask)
Declare a runnable and a handler as shown:
final Runnable updateMainUIThread = new Runnable() {
public void run() {
Toast.makeText(getBaseContext(), "Communicating with the main thread!!", Toast.LENGTH_LONG).show();
}
};
private final Handler handler = new Handler();`
And use it like this:
handler.post(updateMainUIThread);
I have a problem. I'm using a FileObserver, which moves new files from the watched directories to another, former specified directory. In my thoughts there should be shown a toast message that says 'File xy has been moved', as long as the observer watches the directory, also if the applications is only in the background. But I didn't get it working.
It always tells me, that there is a RuntimeException, and that it cannot been done without calling Looper.prepare().
05-11 13:21:28.484:
WARN/System.err(3397):
java.lang.RuntimeException: Can't
create handler inside thread that has
not called Looper.prepare()
I tried the way with using an handler too, but I also didn't get it to work.
Has someone else an idea?
Thanks in advance.
Best regards, Tobi
Before your Toast statement add the following :
runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
});
This will make it run on UI thread.
Hope this helps.
Obviously, your FileObserver runs(or is) another thread. You can not modify the UI from non-UI thread. Pass a Handler to your FileObserver and send messages from it. Read about Handlers.
What are you using for the context of the Toast message? That will have to have a way to display something on the screen.
Put the following code in your class:
// Need handler for callbacks to UI Threads
// For background operations
final Handler mHandler = new Handler();
// Create Runnable for posting results
final Runnable mUpdateResults = new Runnable() {
public void run() {
// Show the toast here.
}
};
and in your fileobserver's thread call place following fragment of code:
mHandler.post(mUpdateResults);
and don't use the getApplicationContext() instead try YourClassPhysicalName.java for the context of the Toast.
I am now working on an android app in which I need to display a text after some processing is done.
I'm using a Thread to run a process in the back while my progress dialog is being displayed to the user. The Thread works properly and I've followed it step by step and, apparently, it also ends fine; however, the method in which I call it does not seem to come to an end (at least, during a normal cycle) because the text I am setting afterward does display immediately, I have to wait and do some other action (like in order for it to display
Below is the piece of code I'm having trouble with:
private OnClickListener saldoDisp = new OnClickListener(){
public void onClick(View v){
int x = s2.getSelectedItemPosition();
branchSel = arrSucsId[x];
mainProc();
saldoAdminTex.setText(strSaldo); //The late one
}
};
public void mainProc(){
chekP = new Thread (null,doProc,"Background");
chekP.start();
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true, false);
}
private Runnable doProc = new Runnable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
};
So I do get the "Task completed properly" but seems like it still waits for something else, any clues guys?
Thanks for taking a bit of your time to check it out =).
saldoAdminTex.setText(strSaldo); //The late one
is going to get called immediately. It doesn't wait until after the Thread started in mainProc ends. You also cannot dismiss the Progress Dialog in your runnable. You can only do UI related things on the main UI thread.
It would help you to read the article on Painless Threading on the Android Dev site.
About your ProgressDialog, please see this answer about how to use a AsyncTask with a ProgressDialog.
Looking at your code, this:
saldoAdminTex.setText(strSaldo);
would potentially be executed before your thread finishes as the thread will be running in parallel to that line.
An alternative way would be to do this:
public void mainProc(){
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true,false);
handler.post(new Runable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
saldoAdminTex.setText(strSaldo);
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
});
}
I'm trying to create a simple multiplayer game. There's a WorkerService which is supposed to handle all network communication and all interaction between this service and my Activities is done with AIDL. I think this is a standard approach - to enable two way interaction I use also an IWorkerCallback interface (also AIDL).
The problem is that callbacks have to change things in UI which may be done only in UI thread. I've created a Handler (in UI thread) and believed that this is an obvious solution. But, surprisingly, it's not working.
My LoungeActivity calls startServer() method of IWorker interface. Corresponding method of my WorkerService does some job and makes a callback - this works fine. Then WorkerService spawns a new thread and callback from this thread results in a bad Exception being thrown:
Can't create handler inside thread that has not called Looper.prepare()
Here's some code to make it clear:
startServer() implementation:
private void startServerImpl(String name, float latStart, float latEnd,
float lonStart, float lonEnd)
{
// some instructions here
// this works fine:
callback.notifySocketCreated();
// my naughty thread:
new ServerThread().start();
// some instructions here
}
ServerThread code:
private class ServerThread extends Thread {
#Override
public void run()
{
//some instructions here
// this call will cause an error
callback.notifyGameRegistered();
}
}
Every method from callback looks like that:
public void notifyGameRegistered() throws RemoteException
{
handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED));
}
In Handler's handleMessage() method I'm doing a simple switch(msg.what) and in every case there's a simple UI modification (showing a Toast, changing Text, etc.).
I have no idea why is this Exception thrown.. I've managed to fix it by packing code into a Runnable and calling runOnUiThread() but it still makes me curious - shouldn't a Handler always run in thread that created it? Or maybe I'm doing something wrong?
I know this is a bit late - but the problem is that you called dispatchMessage().
The correct method is sendMessage().
dispatchMessage() will call handleMessage() on the same thread.
I am guessing the problem is not your Handler being on the wrong thread - but that the UI is trying to create a Handler somewhere in yout onHandle() method. Because onHandle() is called on the wrong thread, you are getting an exception.
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg)
{
if (msg.callback != null) {
handleCallback(msg);
} else {
handleMessage(msg);
}
}
You have to somehow call the offending function from the main thread.
The function that changes the UI should be in the activity that owns the UI.
This link should help you out:
http://android-developers.blogspot.com/2009/05/painless-threading.html