I use an AsyncTask class for execute a task and show an ImageView.
But I execute this task every 10 seconds, for this I call the same task in :
onPostExecute() method.
It's work but the imageView refresh after 10 seconds, why ?
This is my code :
#Override
protected void onPostExecute(Void result) {
ProgressBar progress = (ProgressBar) rootView.findViewById(R.id.progress);
progress.setVisibility(View.GONE);
ImageView imageView = (ImageView) rootView.findViewById(R.id.myView);
imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
SVG svg;
InputStream is = null;
try {
is = new FileInputStream(mySVG);
svg = SVG.getFromInputStream(is);
Drawable drawable = new PictureDrawable(svg.renderToPicture());
imageView.setImageDrawable(drawable);
} catch (SVGParseException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imageView.refreshDrawableState();
long start = System.currentTimeMillis();
while ((System.currentTimeMillis() - start) < 10000) {
}
AsyncTask<Object, Integer, Void> t = new Task(rootView).execute();
}
This code refresh the imageView after 10 seconds, but I would refreshed immediately, wait 10 seconds and execute another Task...
Wow, you're using an AsyncTask and then "eat CPU" in the onPostExecute()
while ((System.currentTimeMillis() - start) < 10000) {
}
Don't do this.
Use a Handler / Runnable combination.
Here's an example:
In your Activity you do:
private Handler timerHandler;
private Runnable timerRunnable;
// ...
#Override
public void onCreate() {
super.onCreate();
timerHandler = new Handler();
timerRunnable = new Runnable() {
#Override
public void run() {
// do your refresh here
timerHandler.postDelayed(timerRunnable, 10000);
}
};
timerHandler.post(timerRunnable);
}
Related
Hi people I am getting problem in getting my latest JSON value after every 10 seconds. I have developed this code and now I am stucked in this. When I run this code it shows the value after second and did not get updated the second time. I have implemented the handler but it is also not working here.
public class MainActivity extends AppCompatActivity {
TextView a,b,c,d,e,f,g,h;
String result = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a=(TextView) findViewById(R.id.a);
b=(TextView) findViewById(R.id.b);
c=(TextView) findViewById(R.id.c);
DownloadTask task = new DownloadTask();
task.execute("https://api.thingspeak.com/channels/12345/feeds.json?results=1");
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
new Handler().postDelayed(new Runnable() {
public void run() {
search(result);
}
}, 10000);
}
public void search(String result){
try {
JSONObject jsonObject = new JSONObject(result);
JSONArray weatherInfo = jsonObject.getJSONArray("feeds");
JSONObject legsobject = weatherInfo.getJSONObject(0);
a.setText(legsobject.getString("field1"));
b.setText(legsobject.getString("field2"));
c.setText(legsobject.getString("field3"));
}catch (JSONException e) {
e.printStackTrace();
}
}
}
}
I want to get my value refreshed after every 10 seconds and it is not doing it.
Can any one guide me that how can I make it possible.
Try this code ..
private final int INTERVAL_MILLI = 60000; // define your time..
Handler mHandler;
#Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(SyncData);
}
Runnable SyncData = new Runnable() {
#Override
public void run() {
// call your code here..
Log.e(TAG, "SyncData1: " + new java.sql.Date(System.currentTimeMillis()).toString());
final String Token = AppSetting.getStringSharedPref(mContext, Constants.USER_KEY_TOKEN, "");
if (!TextUtils.isEmpty(Token) && !CommonUtils.isServiceRunning(mContext)) {
Log.e(TAG, "SyncData2: " + new java.sql.Date(System.currentTimeMillis()).toString());
startService(new Intent(mContext, SyncService.class));
}
callSyncData();
}
};
public void callSyncData()
{
mHandler.postDelayed(SyncData, INTERVAL_MILLI);
}
and callSyncData() method called in activity onCreate method and run method.
To begin with, I don't like the idea of hammering the server with a request every 10s even nothing changes really. If you can move to a solution with notification from the server it will be better.
If you still need to do that you can use three common solutions to fire a repeating task with a period:
1- Use Timer & TimerTask
For this solution you need to declare your timer task to run:
final TimerTask repeatedTask = new TimerTask() {
#Override
public void run() {
//you stuff here
}
};
Then you need to schedule your task using a timer like below:
final Timer timer = new Timer();
timer.scheduleAtFixedRate(repeatedTask,0, 10 * 1000);
==> Don't forget to call timer.cancel(); when your are done (or activity pause, stop, ...)
2- Use ScheduledThreadPoolExecutor
This is basically a replacing for Timer task starting android 5.0. The setup is more easy and straightforward like below:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
//you stuff here
}
}, 0, 10, TimeUnit.SECONDS);
==> don't forget to shutdown your executor when you are done by calling : executor.shutdown();
3- Use Handler
The tip here is to repost the runnable after downloading your json like mentionned in the previous answer.
You can use TimerTask and Timer. If you need to update UI components you should run it on UI thread.
final TimerTask yourRepeatedTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//your code here
}
});
}
};
And the Timer which schedules your task in a given interval. In your case, it is 10s. Make sure to give the interval in milliseconds.
final Timer timer = new Timer();
timer.scheduleAtFixedRate(yourRepeatedTask ,0, 10 * 1000);
At last call timer.cancel() to stop the timer.
#Override
protected void onPause() {
if (timer != null) {
timer.cancel();
}
super.onPause();
}
I'm calling several AsyncTasks to do a job. In order to know when they are done. I have an object (synchronized) with a numerator that holds the number of current running AsyncTasks.
After deploying all of them I do the following:
final ProgressDialog pd = new ProgressDialog(this);
pd.setMessage(getString(R.string.please_wait));
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setCancelable(false);
pd.setProgress(0);
pd.setMax(Utils.getAsyncs());
pd.show();
new Thread(new Runnable() {
#Override
public void run() {
while (Utils.getAsyncs() > 0)
pd.setProgress(pd.getMax() - Utils.getAsyncs());
runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
}
});
}
}).start();
When the dialog shows, it starts progressing but at some point it gets stuck til the end of everything and then dismisses (as expected).
I tried to put
pd.setProgress(pd.getMax() - Utils.getAsyncs());
also inside a runOnUiThread but that made things worse and I'm sure I'm missing something else. hence my question. Thanks
edited by request:
public static int getAsyncs() {
return asyncs;
}
edit 2: I did the following based on a comment
while (Utils.getAsyncs() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
runOnUiThread(new Runnable() {
public void run() {
pd.setProgress(pd.getMax() - Utils.getAsyncs());
}
});
}
and it seems to be better
In your class fields
private Handler progressHandler = new Handler();
private Runnable progressRunnable = new Runnable() {
#Override
public void run() {
progressDialog.setProgress(progressValue);
progressHandler.postDelayed(this, 1000);
}
};
When the time consuming thread is started
// Here start time consuming thread
// Here show the ProgressDialog
progressHandler.postDelayed(progressRunnable, 1000);
When the time consuming thread ends
progressHandler.removeCallbacks(progressRunnable);
/// Here dismiss the ProgressDialog.
ADDED:
Instead new Thread(new Runnable) that you probably use for your time consuming code I propose to do this:
To initialize the task :
MyTask task = new MyTask();
task.execute();
// Here show the PorgressDialog
progressHandler.postDelayed(progressRunnable, 1000);
Add this private class inside your main class:
private class MyTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
//Here do your time consuming work
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
// This will be called on the UI thread after doInBackground returns
progressHandler.removeCallbacks(progressRunnable);
progressDialog.dismiss();
}
}
do something lik this
new Thread(new Runnable() {
public void run() {
while (prStatus < 100) {
prStatus += 1;
handler.post(new Runnable() {
public void run() {
pb_2.setProgress(prStatus);
}
});
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(prStatus == 100)
prStatus = 0;
}
}
}).start();
I have a issue with using a timer on a listview.
In the list item I showed using sqlite values. There is a textview which showing time difference of last updated time of the data and current time. i have to show it in every one second. so the user can know how long he updated the record.
I tried this in several ways.
First way
I tried to add timer in adapter class. so for every item new timer is created. so application crashed because of many timers run simultaneously.
Second way
I tried using adapter.notifyDataSetChanged() way. Like as this.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (adapterChatThread != null) {
adapter.notifyDataSetChanged();
}
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
I move to another activity when click on list item and user can come back to this Activity.
so in Onresume I used
timerHandler.postDelayed(timerRunnable, 500);
and OnPause
timerHandler.removeCallbacks(timerRunnable);
Issue is data is not showing well. I mean in every second data difference is not one second. some time differnce is 2sec, 5 sec, .. etc.
means timer is not working as I expected.
Third way
I used a asynctask and call it in every second using a timer.
class ThreadTimer extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
if (adapter != null)
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this as in here
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
new ThreadTimer().execute();
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
previous issue triggered. (data not showing well)
Fourth way
Using AsyncTask as this
class ThreadTimer extends AsyncTask<Void, Void, Void> {
void Sleep(int ms) {
try {
Thread.sleep(ms);
} catch (Exception e) {
}
}
#Override
protected Void doInBackground(Void... params) {
while (threadRun) {
Sleep(1000);
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this class in OnResume.
In on pause I set threadRun= false;
issue is same.
please help me.
My requirement is update list item in every second.
Thank you.
edit
here is my adapter class textview update code.
Date lastUpdatedTime;
final ChatThreadDAO ctd = new ChatThreadDAO();
long timeForNextResponse = ctd.getLastRespondedTime(vct.get(position).getThread_id());
try {
if (vct.get(position).getThread_read_status() == 1 && timeForNextResponse > 0) {
final long respTime = timeForNextResponse;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
lastUpdatedTime = formatter.parse(vct.get(position).getLast_updated_time());
final long timeDiff = (new Date()).getTime() - lastUpdatedTime.getTime();
if (timeDiff <= respTime) {
timeForNextResponse = respTime - timeDiff;
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), timeForNextResponse);
holder.tvChatTimer.setVisibility(View.VISIBLE);
holder.tvChatTimer.setText(timeForNextResponse / 1000 + "");
} else {
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), 0);
}
} else {
holder.tvChatTimer.setVisibility(View.INVISIBLE);
}
} catch (ParseException e) {
e.printStackTrace();
}
here vct is
Vector vct;
I assign the values to vector in adapter class constructer.
Here is an example similar to your case.
private class connectionControl extends Thread {
boolean stop_ = false;
public void stop_() {
this.stop_ = true;
}
public void run() {
System.out.println("Thread started:" + getClass().getSimpleName());
while(!this.stop_) {
try {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
int rightNow = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60;
if(rightNow - lastUpdatedTime > 10) {
wirelessIcon.setImageResource(R.drawable.wirelessred);
}
else if(rightNow - lastUpdatedTime > 5) {
wirelessIcon.setImageResource(R.drawable.wirelessyellow);
}
else {
wirelessIcon.setImageResource(R.drawable.wirelessgreen);
}
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Thread stoped:" + getClass().getSimpleName());
}
}
You set your lastUpdatedTime the same way you created rightNow whenever you call notifyDataSetChanged() method of your adapter.
Hi currently i have the following code which utilizes Asycn Task and Timer.
My async task is basically trying to send a HTTP GET method from a URL where the response from the server could varies depending on connection and load.
What i would like to do is to have a timed async task. Where, it will schedule an AsyncTask every X second BUT if there is currently an Async Task in progress i would have to kill it first. Then start a new one.
Here is the code that i have at the moment:
private static boolean running = false;
Timer myTimer;
protected void onCreate(Bundle savedInstanceState) {
/* REST OF CODE OMITTED */
MyTimerTask myTask = new MyTimerTask();
myTimer = new Timer();
myTimer.schedule(myTask, 0, 10000);
}
/* REST OF CODE OMITTED */
private class MyTimerTask extends TimerTask {
public void run() {
if(!running){
Log.i("TAG", "NEW TIMER STARTED.");
RetrieveChatMessage task = new RetrieveChatMessage();
task.execute();
running = true;
}else{
running = false;
}
}
}
private class RetrieveChatMessage extends AsyncTask<String, Void, ArrayList<Chat>> {
#Override
protected ArrayList<Chat> doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<Chat> cList = null;
String jResult = null;
Log.i("TAG", "RETRIEVING CHAT MESSAGE");
try {
jResult = ((new HttpRetriever())).getChatList(mAccount.email, mAccount.passwd);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(jResult != null){
Log.i("TAG", "JSON DATA: " + jResult);
cList = (new ChatHandlers()).getChatList(jResult);
}else{
cList = null;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("TAG", "JSON Exception " + e.toString());
}
return cList;
}
#Override
protected void onPostExecute(final ArrayList<Chat> result) {
Log.i("TAG", "ON POST EXECUTE");
if(result != null){
// Do something here
}
}
}
To be honest the code above works with slight issues:
1. It seems to execute the Async randomly, instead of every 10 seconds.
2. When i go to another activity, somewhat it prevents other Async task from doing its job (Which is also trying to retrieve JSON response from server).
I am not too worried about the later problem (and that is not the question i am asking). I just would like to know how to have a proper timed Async Task. Can anyone point me to a direction.
Thank you.
EDIT #1:
after reading #thepoosh comment's i tried the following (i put it in onCreate):
scheduleTaskExecutor= Executors.newScheduledThreadPool(5);
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
// Parsing RSS feed:
// myFeedParser.doSomething();
Log.w("THUMBQOO", "NEW TASK STARTED");
retrieveChat();
}
}, 0, 15, TimeUnit.SECONDS);
Result: i have a consistent execution of Task. However, it seems that retrieveChat(); is never be called after the first execution.
Actually AsyncTask is not used for long operations .Check Here
You should use a Thread that uses a interface to notify UI or you can simply use a Handler which is the most Preffered way in android. Simply you can do a task repeatedly for every 10 seconds by
handler.postDelayed(new Runnable() {
#Override
public void run() {
// do work
handler.postDelayed(10000);
}
}, 10000);
Declare a Handler object to maintain future task executor...
private Handler mTimerHandler = new Handler();
Write a thread which will execute your future task...
private Runnable mTimerExecutor = new Runnable() {
#Override
public void run() {
//write your code what you want to do after the specified time elapsed
if(!running){
RetrieveChatMessage task = new RetrieveChatMessage();
task.execute();
running = true;
}else{
running = false;
}
}
};
Call your future tast executor with time using hanlder...
mTimerHandler.postDelayed(mTimerExecutor, 10000);
You can cancle your future task executor any time by this...
mTimerHandler.removeCallbacks(mTimerExecutor);
I am not sure if this is a very good way of accomplishing this (my answer here below) :
Use a Handler, create a HandlerThread and keep posting messages to this handler.
For the handlers "handleMessage" method, you can do your task and again send a message back to the MessageQueue.
HandlerThread thread = new HandlerThread(<name>);
thread.start();
Looper looper = thread.getLooper();
CustomHandler handler = new CustomHandler(looper);
// The CustomHandler class
class CustomHandler extends Handler {
public CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
//Do your operation here
handler.sendEmptyMessageDelayed(msg, <delayTime>);
}
}
I want to write a download manager app, in the activity I add a progress bar which show the current progress to the user, now if user touch the back button and re-open the activity again this ProgressBar won't be updated.
To avoid from this problem I create a single thread with unique name for each download that keep progress runnable and check if that thread is running in onResume function, if it is then clone it to the current thread and re-run the new thread again but it won't update my UI either, Any ideas !?
#Override
public void onResume()
{
super.onResume();
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
for (int i = 0; i < threadArray.length; i++)
if (threadArray[i].getName().equals(APPLICATION_ID))
{
mBackground = new Thread(threadArray[i]);
mBackground.start();
downloadProgressBar.setVisibility(View.VISIBLE);
Toast.makeText(showcaseActivity.this
, "Find that thread - okay", Toast.LENGTH_LONG).show();
}
}
private void updateProgressBar()
{
Runnable runnable = new updateProgress();
mBackground = new Thread(runnable);
mBackground.setName(APPLICATION_ID);
mBackground.start();
}
private class updateProgress implements Runnable
{
public void run()
{
while (Thread.currentThread() == mBackground)
try
{
Thread.sleep(1000);
Message setMessage = new Message();
setMessage.what = mDownloadReceiver.getProgressPercentage();
mHandler.sendMessage(setMessage);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
catch (Exception e)
{/* Do Nothing */}
}
}
private Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message getMessage)
{
downloadProgressBar.setIndeterminate(false);
downloadProgressBar.setProgress(getMessage.what);
if (getMessage.what == 100)
downloadProgressBar.setVisibility(View.GONE);
}
};
Download button code:
downloadBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
downloadProgressBar.setVisibility(View.VISIBLE);
downloadProgressBar.setIndeterminate(true);
downloadProgressBar.setMax(100);
Intent intent = new Intent(showcaseActivity.this, downloadManagers.class);
intent.putExtra("url", "http://test.com/t.zip");
intent.putExtra("receiver", mDownloadReceiver);
startService(intent);
updateProgressBar();
}
});
I'd strongly recommend reading the Android Developer blog post on Painless Threading. As it states, the easiest way to update your UI from another thread is using Activity.runOnUiThread.