Ok this is a very weird problem I am having, and I'm pretty sure that I am messing up somewhere, but I can't quite figure out where.
What I am trying is -
Schedule a Timer to execute a TimerTask every five seconds
The TimerTask in turn executes an AsyncTask (which in this case simple sleeps for a second before returning the static count of the number of AsyncTasks).
Finally, the aforementioned count is updated in the UI.
And of course, the appropriate Handlers and Runnables have been used to post asynchronous messages from other threads to the UI.
This code executes only once. I expect it to fire every 5 seconds. Here's the code.
Note: I had no idea what to do with the Looper. I put it there after trial and error!
public class TimerAsyncMixActivity extends Activity {
public static final String TAG = "TimerAsyncMix";
static int executionCount = 0;
Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Timer().schedule(new MyTimerTask(this), 0, 5000);
}
class MyAsyncTask extends AsyncTask<String, Void, Integer>{
#Override
protected Integer doInBackground(String... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ++executionCount;
}
#Override
protected void onPostExecute(Integer result) {
mHandler.post(new UpdateUiThread(TimerAsyncMixActivity.this, result));
super.onPostExecute(result);
}
}
}
class MyTimerTask extends TimerTask{
private TimerAsyncMixActivity tma;
public MyTimerTask(TimerAsyncMixActivity tma) {
this.tma = tma;
}
#Override
public void run() {
Looper.prepare();
Log.d(TimerAsyncMixActivity.TAG, "Timer task fired");
tma.new MyAsyncTask().execute();
Looper.loop();
Looper.myLooper().quit();
}
}
class UpdateUiThread implements Runnable{
int displayCount;
TimerAsyncMixActivity tma;
public UpdateUiThread(TimerAsyncMixActivity tma, int i) {
this.displayCount = i;
this.tma = tma;
}
#Override
public void run() {
TextView tv = (TextView) tma.findViewById(R.id.tvDisplay);
tv.setText("Execution count is : "+displayCount);
}
Can anyone point me to what I'm doing wrong?
techie, this is how I implemented similar things. I'm won't claim that this is the best way, but it has worked for me and doesn't look too bad.
I have the following code in my activity. I create an async task when the activity starts and I stop it onPause. The AsyncTask does whatever it needs to do, and updates the UI on onProgressUpdate() (which is run on the UI thread, so there's no need to use a Handler).
private Task task;
#Override
protected void onPause() {
task.stop();
task = null;
}
#Override
protected void onResume() {
task = new Task();
task.execute();
}
private class Task extends AsyncTask<Void, String, Void> {
private boolean running = true;
#Override
protected Void doInBackground(Void... params) {
while( running ) {
//fetch data from server;
this.publishProgress("updated json");
Thread.sleep(5000); // removed try/catch for readability
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
if( ! running ) {
return;
}
String json = values[0];
//update views directly, as this is run on the UI thread.
//textView.setText(json);
}
public void stop() {
running = false;
}
}
Do not use a timer. If your phone goes to sleep, the timer is suspended too. Use AlarmManager.
Related
I have designed an app that gets the network information and updates the UI every 5 seconds.
It is advised to do the background processes on a separate thread than the UI thread, and I did so...but I still get an error that:
"I/Choreographer﹕ Skipped 3730 frames! The application may be doing
too much work on its main thread."
Why is that?
Here's my code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wifiTextView = (TextView)findViewById(R.id.wifi_textView);
ipTextView = (TextView)findViewById(R.id.ip_val_textView);
// and so on
//Updating the UI every mInterval seconds, using a separate thread than UI thread
Thread backgroundThread = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(mInterval);
runOnUiThread(new Runnable() {
#Override
public void run() {
//Log.d(DEBUG_TAG, "run(): Background thread");
MyNetwork network = new MyNetwork(getApplicationContext()); // passing the context
updateUI(network);
}
});
}
} catch (InterruptedException e) {
wifiTextView.setText("Exception: Please Close and Restart the App");
}
}
};
backgroundThread.start();
}
In the same MainActivity class, I have this private function:
private void updateUI(MyNetwork network){
// Handles updating the textviews in the UI
//Log.d(DEBUG_TAG, "updateUI(DeepstreamNetwork)");
if (network.isConnected()){
wifiTextView.setText(R.string.wifi_is_on);
wifiTextView.setTextColor(Color.GREEN);
ipTextView.setText(network.getIpAddress());
else {
wifiTextView.setText(R.string.wifi_is_off);
wifiTextView.setTextColor(Color.RED);
ipTextView.setText("N/A");
}
}
UPDATE
So, I have updated my MainActivity class to have this MyAsyncTask method to handle background work...here's my code:
private class MyAsyncTask extends AsyncTask<Void, Void, MyNetwork> {
#Override
protected void onPostExecute(MyNetwork network) {
updateUI(network);
}
#Override
protected MyNetwork doInBackground(Void... params) {
MyNetwork network = new MyNetwork(getApplicationContext()); // passing the context
return network;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
Two issues:
1) how do I force it to do this background task every 5 seconds. Since the network status changes every few secs (disconnection etc...), so I want it to update the UI respectively.
2) should I call it like this in MainActivity: new MyAsyncTask().execute();
Thanks all
I dont know why you called it Thread backgroundThread = new Thread() because runOnUiThread() is really the main Thread.
You should try this in an asynctask where you only update the UI in onPostExecute()
EDIT:
private class MyAsyncTask extends AsyncTask<Void, Void, String> {
private MyNetwork network;
#Override
protected void onPreExecute() {
this.network = new MyNetwork(getApplicationContext());
}
#Override
protected String doInBackground(Void... params) {
return network.getIpAddress();
}
#Override
protected void onPostExecute(String ipAddress) {
if (this.network.isConnected()){
wifiTextView.setText(R.string.wifi_is_on);
wifiTextView.setTextColor(Color.GREEN);
ipTextView.setText(ipAddress);
else {
wifiTextView.setText(R.string.wifi_is_off);
wifiTextView.setTextColor(Color.RED);
ipTextView.setText("N/A");
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
I have an AsyncTask inside a fragment, which is being executed every second using a Timer. The AsyncTask loads data into a ListView, and when the user clicks on a ListView item, it switches to another fragment.
The timer doesn't stop, so it keeps executing itself and finally, gives me an error when it tries to load the data into the ListView.
I already tried looking for answers, and have implemented those in my code-
class HttpGetAsyncTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onCancelled() {
Log.d("PORTS Cancelled","cancelled");
}
#Override
protected String doInBackground(String... q) {
String v = null, c = null;
for(int countervar=0;countervar<1;countervar++){
if(load.isCancelled())
break;
//All my code here
}
return c;
}
protected void onPostExecute(String result) {
if(isCancelled()||!isAdded()){
return;
}
else{
SimpleAdapter adapter = new SimpleAdapter(getActivity(),
ports, R.layout.playout, new String[] { "name",
"code", "type" }, new int[] { R.id.portn, R.id.portc,
R.id.portv });
adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
}
}
#Override
public void onPause() {
super.onPause();
timer.cancel(); //timer is the name of the Timer
doAsynchronousTask.cancel(); //doAsynchronousTask is the TimerTask
if(load!=null) //load is the AsyncTask
if(!load.isCancelled())
load.cancel(true);
}
#Override
public void onDestroy() {
super.onDestroy();
timer.cancel();
doAsynchronousTask.cancel();
if(load!=null)
if(!load.isCancelled())
load.cancel(true);
}
The timer (Called in onCreateView)-
handler = new Handler();
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
load = new HttpGetAsyncTask();
load.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 10000);
Please let me know where I'm going wrong and what I can do to fix this problem. Thanks.
When the doAsynchronousTask task is scheduled the load variable is replaced with a new HttpGetAsyncTask. So more than one AsyncTask can run a the same time, and when you stop the task, calling:
load.cancel(true);,
you are only cancelling the AsyncTask referenced by load variable, but others tasks can continue to work in backgroud (without any handle for stopping them).
A solution can be, to stop the AsyncTask before start another one.
What about adding a boolean flag in the loop as the condition controlling the loop?
Then you can set it to false to stop the task in onPause()
I need to send one command to the server from an android activity at regular intervals of time and then receive the output and display it on the Layout of the activity.
How can I achieve the above task?
I think this is the sort of thing you're looking for:
public void myAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
BackgroundTask backgroundTask = new BackgroundTask();
// The above is the class that performs your task
backgroundTask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 50000); //this runs every 5 seconds. Feel free to change it
}
Change it according to your needs.
In the above case for each and every time one async task object will be created but in this case objects will not be created multiple times and with out completing first request the send request will be started...
private void startFectchingTheData() {
asynT.execute();
}
Runnable rannable = new Runnable() {
#Override
public void run() {
asynT.execute();
}
};
Handler handler = new Handler();
AsyncTask<Void, Void, Void> asynT = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
// Write the fetching logic here
return null;
}
protected void onPostExecute(Void result) {
int interval = 5000;
handler.postDelayed(rannable, interval);
};
};
protected void onDestroy() {
handler.removeCallbacks(rannable);
};
I have tried AsyncTask, Handler, and a simple Thread to achieve what I am trying to do but I just cannot get any of them to work, below is the logic that I need to use to update my UI...
public class GameProcessor extends Thread {
#Override
public void run() {
for (Integer integer : sequence) {
//set button state to pressed
Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//set button state to un-pressed
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Please do not respond with, you cannot update the UI from anywhere but the main thread, I already know this and need a solution on how to loop through some values from the backend while updating the UI at the same time. From what I can tell, AsyncTask and Handler will not help much.
Any help will be very appreciated!
If you know about the UI thread, why don't you:
runOnUiThread(new Runnable() {
public void run() {
//set button state to un-pressed or pressed.. or whatever you want..
}
});
I don't understand your problem
Create a member Handler object in your Activity (mHandler). Whenever you want to update your UI from the other thread, call
mHandler.post(new Runnable(){
public void run(){
//update the button state
}
});
The Handler will call this run() method in the UI thread for you.
This is simplified. You will probably want to create your Runnables as member variables so your aren't recreating the same Runnables over and over.
If you want to loop through some valuse, while updating the UI at the same time, then you may consider using AsyncTask and may use this feature:
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
And from :
protected Long doInBackground(URL... urls) {
calculate value
publishProgress(value);
return totalSize;
}
This will keep on updating UI thread with intermediate values you send.
In case you already know this and have tried and it does not solve your purpose, am sorry :)
or you can try this:
public void run() {
Console.post(new Runnable() {
public void run() {
Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
}
});
}
In order to update your UI thread you can use the handler. Here's a simple example of using AsyncTask and Handler:
private static final String MESSAGE_KEY = "com.example.mypackage.MSGKEY";
private static final int MESSAGE_AUTHENTICATING = 0;
private static final int MESSAGE_AUTHENTICATED = 1;
/**
* This handler will update UI
*
*/
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.getData().getInt(MESSAGE_KEY)) {
case MESSAGE_AUTHENTICATING:
hashstream_stream.setVisibility(View.GONE);
hashstream_progress.setVisibility(View.VISIBLE);
break;
case MESSAGE_AUTHENTICATED:
hashstream_stream.setVisibility(View.VISIBLE);
hashstream_progress.setVisibility(View.GONE);
break;
default:
break;
}
}
};
/**
* This method should be used to update UI thread.
*
* #param value
*/
private void postMessage(int value) {
Message msgObj = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt(MESSAGE_KEY, value);
msgObj.setData(bundle);
handler.sendMessage(msgObj);
}
/**
* AsyncTask Helper class as network op
*
*
*/
private class StreamHashTagTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//Do actual operation in here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
postMessage(MESSAGE_AUTHENTICATED);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
postMessage(MESSAGE_AUTHENTICATING);
}
/**
* If you need to update progress override onProgressUpdate() method.
* Since I am indeterminate using progress bar as authentication time
* cannot be calculated , I don't need update here
*/
}
Did you try?
instanceOfActivity.runOnUiThread(new Runnable(){
#Override
public void run() {
Console.getBottomLeft().getButton().setBackgroundResource(R.drawable.button_focused);
}
});
But in this case, I don't suggest you use an activity in another object.
Please using interface like above:
public interface INotifyChange {
void notify(object value); // Example: void notify(int progress);
}
In your activity where invoke GameProcessor
INotifychange mNotifier;
mNotifier = new INotifyChange() {
#Override
public void notify(object value) {
runOnUiThread(new Runnable(){
#Override
public void run() {
//You can update your UI here.
}
});
}
};
// And your GameProcessor
private INotifyChange mNotifier;
public GameProcessor(INotifyChange aNotifier) {
mNotifier = aNotifier;
}
// Where you want to update UI, please invoke
mNotifier.notify(value);
I want to show the progress dialog while loading the images in grid view.
The problem i'm facing was the current thread and Progress Dialog thread running simultaniously.
public String Method1(){
String output="";
final ProgressDialog aProgDialogL = ProgressDialog.show(this, "", "Loading...");
Thread thread = new Thread() {
public void run () {
//My codes
aHandlerL.post(new Runnable() {
#Override
public void run() {
//Post Runnable codes
aProgDialogL.dismiss();
}
});
}
};
thread.start();
/*
*
*
* OTHER CODES
*
*
*/
return output;
}
In the above example I need to run the code inside Progress Dialog Thread. After it finish executing i need to run my "OTHER CODES". How to do it?
.
I tried using Async task. Before async task completes method1 gets extcuted and reurning the string.
public String Method1(){
String result="";
new GetImages().execute();
return result;
}
public class GetData extends AsyncTask<Void, Void, Integer>{
#Override
protected void onPreExecute() {
aProgDialogL = ProgressDialog.show(Main.this, "", "Loading...");
}
#Override
protected Integer doInBackground(Void... params) {
//Progress Dialig Code
return null;
}
#Override
protected void onPostExecute(Integer result) {
aProgDialogL.dismiss();
//OTHER CODES
super.onPostExecute(result);
}
}
You can use Async task. http://developer.android.com/reference/android/os/AsyncTask.html. There is a good tutorial here. http://www.vogella.com/articles/AndroidPerformance/article.html.Also have a look at this link
http://developer.android.com/guide/components/processes-and-threads.html. Use asynctask modify it according to your needs.
doInBackground()- For long running operations. Don't update ui here.
onPreExecute()- update ui before running the operatio nin background.
onPostExecute()- update ui after running the operation.
I would suggest you to take somewhat different approach.
Dont involve any threads in Method1() function.Rather your Method1() function should be run under separate thread.
Below snippet will help you.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.btnPopup))
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new Thread() {
public void run() {
String answer = Method1();
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here you will write the code which is
// to be executed on main thread.
}
});
};
}.start();
}
});
}
public String Method1() {
// Write code
return "result";
}
}
Instead of that : What about use Timer After specific Time Stop Your thread and and write your code you want after stop statement Like that :
Timer timer=new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
thread.stop;
// Other code }
}, Time You want );