I read in a document that when we implement Runnable we are creating a new thread and post any code to run inside that thread and we use handler to perform UI updates on the uithread.
But in my below example
private class AutoIncrementer implements Runnable {
#Override
public void run() {
if(plusButtonIsPressed){
incrementValue();
handler.postDelayed( new AutoIncrementer(), REPEAT_INTERVAL_MS);
}
}
}
Here I used handler.postDelayed() to update the UI with incremented value
and again on implementing onLongClickListener()
plusButton.setOnLongClickListener(
new View.OnLongClickListener() {
#Override
public boolean onLongClick(View arg0) {
plusButtonIsPressed = true;
handler.post(new AutoIncrementer());
return false;
}
}
);
I again use handler.post(new AutoIncrementer())..... Why do I need to use this when I am updating the UI through handler.postDelayed()???
Runnable is not a new thread, it is just a piece of code that can be "run".
Your handler.post within onLongClick is what kicks off the first run of the AutoIncrementer. Then within that code it needs to schedule the next check (as onLongClick is only called once, and not repeatedly while the button is held down).
Related
Is it possible to call Runnable without execute-ing it?
AsyncTask.execute(new Runnable() {
#Override
public void run() {
//TODO your background code
}
});
In iOS a closure can be executed, or just called like a method. In first case there is a small delay, other code chunk can come first to the loop, in second case right at the time when call is done code is Runnable is performed. How is it with Android?
Runnable runnable = new Runnable() {...}
runnable.run();
and if you need to be able to decide where to execute it depending on your current thread: UI or non-UI, you can do something like this
if (Looper.getMainLooper().isCurrentThread()) { ... } else { ... }
Some useful information can be found here Runnable
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);
}
}
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 have an asynctask named myAsync that performs some network operations (fetching data from server, and parsing the json).
I also have a handler created once the activity runs.
I also have a runnable in which i run the asynctask. The reason I am using runnable is because I will be using it inside a Handler's postdelayed method as I want this to be repeated every 1 minute.
Runnable runnable = new Runnable()
{
public void run()
{
new myAsync ().execute();
}
};
Then I am using the above runnable inside my onResume;
#Override
protected void onResume()
{
super.onResume();
handler.postDelayed(runnable, 60000);
}
Whenever I leave the activity, I want the check to stop, so I am calling,
handler.removeCallbacks(runnable);
However, the asynctask keeps on running non stop.
What shall I do ?
The whole point of asynctask is to run a thread on the main thread.
So it does not make sense to run it in Runnable()
What you can do is skip the Runnable and Handler...definitely not needed here. Assuming the AsyncTask is an inner class of your Activity, you can set a member boolean variable and check that in your doInBackground()
public Void doInBackground(Void...params)
{
// this is a boolean variable, declared as an
//Activity member variable, that you set to true when starting the task
while (flag)
{
// run your code
Thread.sleep(60000);
}
return null; // here you can return control to onPostExecute()
// if you need to do anything there
}
This will make the AsyncTask sleep for a minute before running the code again. Then in onPause() or wherever you want you set the flag to false. If you need to update the UI then call publishProgress() inside your loop and put the UI code in onProgressUpdate()
You can remove the AsyncTask and just do the proccess with Runnable in this way you can make the repetitions that you need. If this does not work you can set a flag to stop the proccess like said codeMagic.
runable = new Runnable() {
public void run() {
try {
//Proccess
while (flag)
{
//Proccess
handler.postDelayed(this, 3000);
}
}catch(Exception e)
{
Log.i("Log","Error: "+e);
}
};
handler.postDelayed(runable, 3000);
#Override
public void onPause() {
super.onPause();
flag=false;
handler.removeCallbacks(runnable);
}
#Override
public void onResume() {
super.onResume();
flag=true;
handler.postDelayed(runable, 3000);
}
I hope this help.
I have a problem with unit tests in Android.
My object MyObject has a method start() like this :
public void start() {
final Handler onStartHandler = new Handler();
new Thread() {
#Override
public void run() {
super.run();
onStartHandler.post(new Runnable() {
#Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
}.start();
}
And I want to test that onStart() is called.
So I tried something like that :
public void testOnStartIsCalled() {
assertFalse("onStart() should not be called", mMyObject.isRunning());
mMyObject.start();
assertTrue("onStart() should be called", mMyObject.isRunning());
mMyObject.stop();
assertFalse("onStop() should be called", mMyObject.isRunning());
}
But it doesn't work, I guess it's because it's in a Handler and a new Thread.
My test class extends AndroidTestCase.
What should I do ? What is the best practice for this case ?
Regards.
When I deal with testing some multi-threaded code I try to let the program take as much of its natural flow as possible. Additionally, I avoid the use of sleep statements since you don't get any guarantees that the sleep interval you've chosen is enough to allow the subject of your test to finish what it's doing; you often end up having to choose sleep intervals that are too large and it forces a much slower execution of your test cases.
I would recommend that you try to add some code into the class you're testing, in this case MyObject, which call a listener whenever something happens. It seems that you already have callback methods for onStart() and onStop()(if those are events/callbacks), so those should be getting invoked and you should use them to control the flow of your test. When you get an onStart() event, you should then call stop() and wait for an onStop() event.
Update
First and foremost, you have redundant code:
public void start() {
final Handler onStartHandler = new Handler();
new Thread() {
#Override
public void run() {
super.run();
onStartHandler.post(new Runnable() {
#Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
}.start();
}
Either start a new thread to call onStart() or schedule the runnable on the Handler's thread queue.
Version 1- remove the handler and just let the code be executed in a new thread:
public void start() {
new Thread() {
#Override
public void run() {
super.run();
mIsRunning = true;
onStart();
}
}.start();
}
Version 2- only use the handler to asynchronously execute the callback:
public void start() {
final Handler onStartHandler = new Handler();
onStartHandler.post(new Runnable() {
#Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
And second: I noticed is that if you don't have a Looper, then whatever you post with the Handler will be ignored (thus it will never be called). For more information on the Looper-Handler pattern see the article: Android Guts: Intro to Loopers and Handlers. The Looper and the Handler are supposed to be attached to the same thread (usually the main thread). Additionally, if you're creating the Handler on a separate thread as your Looper, then you'll run into the same problem: anything you post with the Handler will be ignored.
Here are a few more good questions and articles on loopers and handlers:
Just do IT: looper and handler in android
Handler-Looper implementation in Android
The relationships between Looper, Handler and MessageQueue is shown below:
The problem here is that you are calling onStart() which invokes a new thread, and then immediately ask if it is started. There is startup time for the new thread and while that is happening, your test is asking if it is started -- it's not YET.
I bet if you waited by using Thread.sleep(), or a loop, you'd find it is started "eventually".
What is it you're actually trying to test?
If you need the new thread, you might want to read up on threads, synchronize, etc.
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html