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
Related
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).
Ok, I have a game that I am working on, and I need to be able to put different character state animations onto a single view. Here I have goblin_neutral, and goblin_hit, as 2 animation lists, one to show an enemy in a calm state, and the other to show the enemy getting struck. Both are animation lists in separate .xml files in the drawable folder.
AnimationDrawable enemy_neutral_animation, enemy_hit_animation;
ImageView enemy, player;
//...after onCreate()
enemy = (ImageView)findViewById(R.id.ImageView2);
enemy.setBackgroundResource(R.drawable.goblin_neutral);
enemy_neutral_animation = (Animation)enemy.getBackground();
enemy_neutral.start();
//...now jump to the code that triggers a new animation
enemy.setBackgroundResource(R.drawable.goblin_hit);
enemy_hit_animation = (Animation)enemy.getBackground();
enemy_hit_animation.start();
// all of this works^^, as I can see the second animation displayed
// I use a timer to wait for the animation to finish
mTimer.schedule(timerTask, 600);
//mTask is where it stops everytime
timerTask = new TimerTask() {
#Override
public void run() {
enemy.setBackgroundResource(R.drawable.goblin_anim_neutral);
enemy_neutral = (AnimationDrawable)enemy.getBackground();
enemy_neutral.start();
}
};
// I get a wrong thread exception
// E/AndroidRuntime: FATAL EXCEPTION: Timer-0
ViewRootImpl$CalledFromWrongThreadException:
ViewRootImpl$CalledFromWrongThreadException:
Because enemy ImageView object is accessing from run of TimerTask and TimerTask run on separate Thread from UI Thread, but we can only update or access UI elements from UI Thread.
To get it work use runOnUiThread for accessing Views from non-ui Thread.like:
timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// access enemy here
enemy.setBackgroundResource(R.drawable.goblin_anim_neutral);
...
}
});
}
};
The way I will approach this is to use a Handler and Runnable.
In your class, create a handler member variable like so
Handler handler;
Note you want to import Handler as follows:
import android.os.Handler;
Also create a runnable member variable like so
Runnable myRunnable = new Runnable() {
#Override
public void run() {
enemy.setBackgroundResource(R.drawable.goblin_anim_neutral);
enemy_neutral = (AnimationDrawable)enemy.getBackground();
enemy_neutral.start();
}
}
In your constructor, you could initialise the handler.
handler = new Handler();
So, when you need to schedule the task, you simply call
handler.postDelayed(myRunnable, 600);
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
How can I make this happend?
Thread t = new Thread(new Runnable() {
#Override
public void run() {
FacebookConnectTask task =
new FacebookConnectTask("facebookId", "token", "email", facebookGender,0, 0);
task.setOnPreExecuteListener(this);
task.setOnDoneListener(this);
task.execute();
}
});
t.start();
public void onPreExecute() {
progressbar.setVisibility(View.VISIBLE);
}
public void onDone() {
progressbar.setVisibility(View.GONE);
}
Since I am opening a new thread, I can not change a UI element in it, so, How can I manage to do something to the UI, when the task starts and when it's finished?
You could do the work in an AyncTask. The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.
preExecute() and postExecute() offer you access to GUI before and after the heavy lifting occurs in this new thread, you can even pass the result of the long operation to postExecute() to then show any results of processing.
More here: http://developer.android.com/reference/android/os/AsyncTask.html
Example here: http://www.vogella.com/articles/AndroidPerformance/article.html
inside your activity
private Handler myHandler=new Handler();
next in your on done callback
public void onDone() {
myHandler.post(new Runnable(){
#Override
public void run() {
progressbar.setVisibility(View.GONE)
}
})
}
But as already was said. AsyncTask is more siutable for it
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