Found someone has similar issue online here.
This doesn't work:
Timer t = new Timer(false);
t.schedule(new TimerTask() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "msg", Toast.LENGTH_LONG).show();
}
}, 5000);
But if I instantiate the toast outside the timertask then show it inside run,it works.
I think it may relate to the so-called UI thread,
but how exactly ?
try this
Timer t = new Timer(false);
t.schedule(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "msg", Toast.LENGTH_LONG).show();
}
});
}
}, 5000);
Using Timer starts a new thread, I suppose that thread does not have access to getApplicationContext. The proper way to do it is to use Handler and call the postDelayed method of the Handler - which does not start a new thread.
Read about this: http://developer.android.com/resources/articles/timed-ui-updates.html
The link you posted has a working example, which is the proper way to do it:
final Context ctx = this;
Handler mHandler = new Handler();
Runnable
makeToast = new Runnable() {
public void run() {
Toast.makeText(ctx, "msg", Toast.LENGTH_LONG).show();
}
};
mHandler.postDelayed(makeToast, 1000);
Everytime you start an application, it starts on the UI Thread (also called the Main Thread).
Whenever you create a new Thread, or Timer, or AsyncTask, by definition, they're creating new Threads. Threads that aren't the main thread simply don't have permission to modify the UI.
Toast use on UIThread. You can by Handler or runOnUiThread
Related
I would like my code runs all the one minut..
Can anyone explain me how to do it?
private Handler myHandler;
private Runnable myRunnable = new Runnable() {
#Override
public void run() {
//DO WORK
Toast.makeText(getApplicationContext(), " Hello",Toast.LENGTH_SHORT).show();
myHandler.postDelayed(this,60000);
}
};
#Override
public void onCreate() {
super.onCreate();
//call function
myHandler = new Handler();
//
myHandler.postDelayed(myRunnable,60000);
Log.d(this.getClass().getName(), "onCreate");
}
watch this http://goo.gl/DRdaUi
BTW 60 second is a very long time for thread to run! If you have something that runs this long consider using android service instead of thread.
Also do you need to use handler? think again, most of the time there is no need for that. AsyncTask is android first option for multithreading and its a lot simpler. unless AsyncTask can not handle what you have in your mind don't use any other method.
A Timer is a valid solution but it will not execute on the UI thread. And your code tells me this is what you want.
The simplest way to do that would be via a handler and a repeating task:
final Handler handler = new Handler(); // ui thread handler
handler.postDelayed(new MyRunnable(handler), INETRVAL);
Where:
class MyRunnable implements Runnable {
#Override
public void run() {
// do periodical action here
// and.. repeat your task <------------
handler.postDelayed(new MyRunnable(handler), INETRVAL);
}
}
public void displayCurrentLocation(){
mCurrentLocation=mLocationClient.getLastLocation();
TextView coordinates = (TextView)findViewById(R.id.coordinates);
coordinates.setText(mCurrentLocation.getLatitude()+", "+mCurrentLocation.getLongitude());
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
displayCurrentLocation();
}
}, 2000);
}
Just testing the concepts here. I am trying to get an updated current location every 2 seconds and display it in a TextView. I set this up so that it would do it once, but when I added the timer, it will setText once, but the next time it crashes. What is wrong?
I am trying to get an updated current location every 2 seconds and display it in a TextView.
My guess (based on above comment) is you are updating ui from a Timer task. Timer tasks runs on a different thread. You can't update ui from it. You need to update ui from a ui thread.
Use a Handler or runOnUiThread
runOnUiThread(new Runnable() {
public void run() {
// update ui here
}
});
Handler is a better option.
http://developer.android.com/reference/android/os/Handler.html
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
So if you create handler on the ui thread it is bound to it and you can update ui there.
Handler m_handler;
Runnable m_handlerTask ;
int timeleft=100;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 2000);
}
};
m_handlerTask.run();
To cancel the run
m_handler.removeCallbacks(m_handlerTask); // cancel run
Timer runs in a separate Thread and where as you can not touch the UI views in non UI Thread...
use Handler of a TextView or runOnUiThread()
this may help you...
public void displayCurrentLocation() {
mCurrentLocation = mLocationClient.getLastLocation();
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView coordinates = (TextView) findViewById(R.id.coordinates);
coordinates.setText(mCurrentLocation.getLatitude() + ", "
+ mCurrentLocation.getLongitude());
}
});
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
displayCurrentLocation();
}
}, 2000);
I have a ListView which I need to redraw once a second. So I tried having my MainActivity implement Runnable and calling notifyDatasetChanged() from run(). Then I created a ScheduledThreadPoolExecutor to run the MainActivity once a second. But now I'm getting CalledFromWrongThreadExceptions. How can I circumvent this?
So not really sure what you need this for, but you should just use the Handler attached to the main thread instead of using a ThreadPoolExecutor. The reason is that you cannot draw within the context or call notifyDataSetChanged() from any other thread other than the main thread.
Try starting the process by initially:
listView.postDelayed(mRunnable, 1000); since each view is attached to the thread it was attached to the context with, the main thread in this case. So this is a nice convenient method.
Inside MainActivity:
private Runnable mRunnable = new Runnable() {
public void run() {
mAdapter.notifyDataSetChanged();
listView.postDelayed(this, 1000);
}
};
Another approach would be to do the following:
Call the following method notifyDataSetChangedEverySecond() once. It sets a timer that gets called every 1000ms.
private void notifyDataSetChangedEverySecond() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
listview.notifyDatasetChanged();
}
},0,1000);
}
You may use handler instead of ScheduledThreadPoolExecutor, because it creates thread. Or you can just update your ui thread by using runOnUiThread method of context, like this:
runOnUiThread(new Runnable() {
public void run() {
listView.notifyDataSetChanged();
}
}
Use this method where you call notifyDataSetChanged and get error...
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
generateData();
// notifydataset Only the original thread that created a view hierarchy can touch its views
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
}, new Date(System.currentTimeMillis()), 1000);
this working fine with me
i tried both the links : Starting AsyncTask recursively after a gap of 5 minutes and Need advice new AsyncTask recursive calling
but they didnt solve my problem.
i want to use asynctask recursively after every 10sec of gap.
iam creating an app in which a dialog box shows with some content whenever some condition full fill and i need to change that content for that i am trying to call asynctask with a combination of thread and handler.
Thanks in advance!!!!
This repeats every 1000ms:
handler must be final as it is accessed within inner class
final Handler handler = new Handler();
Thread threadObj = new Thread() {
public void run() {
// Asynctask
// delay
handler.postDelayed(this, 1000);
}
};
//to start thread
threadObj.start();
//to stop thread
handler.removeCallbacks(threadObj);
Create a runnable where you start the asynctask again and again and the start the task for the first time by calling handler.postDelayed(repeatingTask , 1000);
private Runnable repeatingTask = new Runnable() {
public void run() {
new MyAsyncTask().execute("my String");
handler.postDelayed(this, 1000);
}
};
This way the runnable will be repeated again and again.Hope this helps you.
public void recur()
{
private Runnable repeat = new Runnable() {
public void run() {
new AsycnCaller().execute();
handler.postDelayed(this, 10000);
}
};
}
call this function where you want Start
and also call this in postexecution of asyntask
I'm createing a quiz that has a time limit and i dont know what to implement to have a timelimit in my level 1 class. what should i implement? can you show me a complete code?
am i correct?
private Runnable task = new Runnable() {
public void run() {
Intent intent = new Intent(getApplicationContext(),MainMenu.class);
startActivity(intent);
}
};
private void onCreate() {
Handler handler = new Handler();
handler.postDelayed(task, 60000);
There are different ways to do it. One way is to use a Runnable and a Handler.
First, define the Runnable:
private Runnable task = new Runnable() {
public void run() {
Log.i(TAG, "Time limit reached!");
// Execute code here
}
};
Then you call it (say at the start of the level, onCreate) with this Handler and postDelayed
Handler handler = new Handler();
handler.postDelayed(task, 60000);
The code within the run() method of the Runnable will execute 60 seconds after you call postDelayed
If you need regular notifications you can also use a CountDownTimer