Android asynctask for max time - java

I'm trying to read data from a physical device.
For acquiring data I use an asynctask to avoid UI blocking.
When I click a button, I should do twice these (for min and max values):
wait 5 seconds;
acquire data for 1 second.
So the code is written in the OnClickListener of the button.
For the first task I use this method:
new android.os.CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() { }
}.start();
For the second I'm using an asynctask and in its doInBackground method I have
while(booleanValueMax || booleanValueMin) {
//code
}
(booleanValueMax and booleanValueMin are volatile boolean). Now I set these two to false using a Timer (outside the asynctask):
Timer min = new Timer();
min.schedule(new TimerTask() {
#Override
public void run() {
booleanValueMin = false;
}
}, 1000);
(same for max)
Now I'd like to use the same asynctask to store max and min values. So I know which data I'm acquiring checking the booleans (in the doInBackground method).
if(booleanValueMax)
//store max
else
//store min
The problem is that these variables are always false. And I don't know why.
Isn't there any other way to accomplish my goal instead of use Timer, CountDownTimer, etc.?I'

Just make two separate asynchtask and call them according to your value i.e.
while(booleanValueMax || booleanValueMin) {
//code
}

You have not shown the code that starts your asynctask, but: all asynctasks share the same thread pool. In the simplest case, it is just one thread. Most likely, your asynctask starts and finishes before any of the variables is set. Asynctasks are intended for long operations that do not need to wait. If you want your code to wait for an event, better use a Thread. (Well, it is possible to post messages/runnables to threads, see Looper and Handler.)

Here's an example:
private void executeBigTask(){
BigTask bigTask = new BigTask();
bigTask.execute();
// Check
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run() {
if (bigTask.getStatus() == AsyncTask.Status.RUNNING){
bigTask.cancel(true);
}
}
}, 10000);
}
protected class BigTask extends AsyncTask<String, String, Integer> {
#Override
protected Integer doInBackground(String... params) {
/**
LONG TASK
*/
return 0;
}
#Override
protected void onCancelled() {
super.onCancelled();
Toast.makeText(MainActivity.this, getString(R.string.task_too_long), Toast.LENGTH_LONG).show();
}
}

Related

update marker position every x time in asynctask

I wanted to mock location of a marker on map. I have list of LatLng values store in ArrayList. I use this value to update on map every second. I need this function to works in AsyncTask so that my UI thread will still responsive.
Initially, I tried using Thread.sleep() but made application not responsive.
protected String doInBackground(Void... voids) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
for (int i = 0; i < waypoint.size(); i++) {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(waypoint.get(i));
try {
Thread.sleep(1000); // Thread sleep made application not responsive.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, 500);
return null;
}
I also tried using .postDelayed but the integer i needs to get declared final which is a problem because I need the integer to change value.
protected String doInBackground(Void... voids) {
for (int i = 0; i < waypoint.size(); i++) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(waypoint.get(i)); // Integer i needs to declare final.
}
}, 1000);
}
return null;
}
Is there any way to do this? Thank you.
The Thread.sleep() approach is OK if you can spare a worker thread. The problem in your code is that the thread you are pausing is the UI Thread, that's why your application freezes. You have to understand that what your doing there is just publishing a runnable to the UI Thread using the Handler construct, nothing more.
In your second approach, you can dump the Handler part and use publishProgress (called from the background) after you override onProgressUpdate (delivered in UI thread) in your AsyncTask based class. It does effectively the same but with less boilerplate. Take a look at https://developer.android.com/reference/android/os/AsyncTask for details.
Finally, to circumvent the final requirement in anonymous classes, you can declare a final array of one element and use position 0 to read/write the value. Hopefully, you won't need to do this too often.
The fastest (but not the most correct when working with MultiThreading) way is:
protected String doInBackground(Void... voids) {
for (final TYPE_OF_WAYPOINT cWaypoint : waypoint) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(cWaypoint);
}
}, 1000);
}
return null;
}
I don't know what was the Type of "waypoint" List, so I wrote "TYPE_OF_WAYPOINTS" as placeholder.
#emandt answer does not work but the idea he gave could work. So I tried and it is working flawlessly with some modified from his answer:
protected String doInBackground(Void... voids) {
for (final TYPE_OF_WAYPOINT cWaypoint : waypoint) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
marker = googleMap.addMarker(new MarkerOptions().position(waypoint.get(0)));
marker.setPosition(cWaypoint);
}
});
try {
Thread.sleep(1000);
} catch (Exception e) {
// catch exception here
}
}
return null;
}
Firstly, I have change the .postDelayed to .post. Then, to delay the operation by one second, I have added Thread.sleep(1000) inside for (...) but outside new Handler(Looper.getMainLooper()).post(...));.
Now, the application could do the process in the background with user still be able to interact with the UI. Thanks.

java - make if for async task time limit

here is my piece of code:
Thread one = new Thread() {
public void run() {
try {
new LongOperation(finalJson)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
.get(30000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
};
one.start();
i want to say if AsyncTask past 30000 MILLISECONDS and didn't finish the job return a message, how i can code this? thanks
I would prefer doing it using an AsyncTask.
Copy-pasting from the link:
AsyncTask enables proper and easy use of the UI thread. This class
allows you to perform background operations and publish results on the
UI thread without having to manipulate threads and/or handlers.
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.
Said this, configuring an AsyncTask is pretty simple, just create a class like the following:
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method works on the UI thread.
//this is the first to run before "doInBackground"
mTextView.setText("we start!");
}
#Override
protected String doInBackground(String... params) {
try {
//do whatever your async task needs to do. This method works async
//you can also call an UI callback from here with the publishProgress method. This will call the "onProgressUpdate" method, and it has to respect his type.
publishProgress("we go on!");
} catch (InterruptedException e) {
Thread.interrupted();
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
//this method works on the UI thread
//it get the "doInBackground" return value.
mTextView.setText(result);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(String... values) {
//this method works on UI thread, so it can access UI components and ctx
mTextView.setText(values[0]);
}
}
This is a basic example on how to create an AsyncTask, you can use it like this (form activity/fragment):
AsyncTaskExample asyncTask = new AsyncTaskExample();
asyncTask.get(30000, TimeUnit.MILLISECONDS);
This will set a timeout on your async operation. Look here for the exact Exception/return
For any further question, ask freely. Hope this helps
Edit:
I just noticed you have an AsyncTask inside your thread. Since AsyncTask is already async, I would avoid doing this and simply call the AsyncTask with the method I gave you before. In that way the AsyncTask will run up to the given TimeSpan :)
See the code below: It may help you.
CountDownTimer timer = new CountDownTimer(3000,1000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
//return a message here;
}
};
timer.start();
And if you have an async task. Then do like below in doInBackground method:
#Override
protected Void doInBackground(Void... voids) {
//simply do your job
CountDownTimer timer = new CountDownTimer(3000,1000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
//return a message here;
return message;
}
};
timer.start();
return your_reult;
}

How to execute AsyncTask in endless loop?

I have AsyncTask class with methods like this(class: ApiConnector):
#Override
protected String doInBackground(Void... voids)
{
return getToken(); //<-- do many the most important things and return String
}
and
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
}
and then in my Activity:
new ApiConnector()
{
#Override
public void onPostExecute(String result)
{
Log.d("here: ", result);
}
}.execute();
It work's fine when I execute this one time, but i have to do this in endless loop to take always fresh token like fresh apples in my market. I tried something like that:
while (true)
{
new ApiConnector()
{
#Override
public void onPostExecute(String result)
{
Log.d("here!", result);
}
}.execute();
Thread.sleep(1000);
}
and many many stupid things, but i can't find working way. All thread bussiness is tricky for me. Give me some kick and I manage this for sure.
You don't want to do this. All AsyncTasks run on one thread. If you infinitely loop inside an AsyncTask, you'll starve all other tasks. If you have each task start a new task, then you'll still risk major starvation issues.
If you want to do this (and I'm not sure you really do, but lets ignore that), the correct way is to use a Thread. A Thread can just have a giant while(true) loop and a sleep statement at the end.
Like hrskrs commented I would prefer using a Handler to execute something repeatedly. The main advantage is that postDelayed makes the run() method execute in the main application thread - so you can access and change UI components.
Here's an example:
public class MyTest implements Runnable {
private final static int INTERVAL = 5000;
private Handler mHandler;
private MyTest() {
mHandler = new Handler();
}
public void start() {
run();
}
public void stop() {
mHandler.removeCallbacks(this);
}
#Override
public void run() {
// put here the logic that you want to be executed
mHandler.postDelayed(this, INTERVAL);
}
}

Wait for multiple AsyncTask to complete

I am parallelizing my operation by splitting it in the exact number of cores available and then, by start the same number of AsyncTask, performing the same operation but on different portions of data.
I am using executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ...) in order to parallelize the execution of them.
I would like to know when every thread finishes its job so that combine all results and perform further operations.
How can I do?
You could also simply decrement a counter in a shared object as part of onPostExecute. As onPostExecute runs on the same thread (the main thread), you won't have to worry about synchronization.
UPDATE 1
The shared object could look something like this:
public class WorkCounter {
private int runningTasks;
private final Context ctx;
public WorkCounter(int numberOfTasks, Context ctx) {
this.runningTasks = numberOfTasks;
this.ctx = ctx;
}
// Only call this in onPostExecute! (or add synchronized to method declaration)
public void taskFinished() {
if (--runningTasks == 0) {
LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this.ctx);
mgr.sendBroadcast(new Intent("all_tasks_have_finished"));
}
}
}
UPDATE 2
According to the comments for this answer, OP is looking for a solution in which he can avoid building a new class. This can be done by sharing an AtomicInteger among the spawned AsyncTasks:
// TODO Update type params according to your needs.
public class MyAsyncTask extends AsyncTask<Void,Void,Void> {
// This instance should be created before creating your async tasks.
// Its start count should be equal to the number of async tasks that you will spawn.
// It is important that the same AtomicInteger is supplied to all the spawned async tasks such that they share the same work counter.
private final AtomicInteger workCounter;
public MyAsyncTask(AtomicInteger workCounter) {
this.workCounter = workCounter;
}
// TODO implement doInBackground
#Override
public void onPostExecute(Void result) {
// Job is done, decrement the work counter.
int tasksLeft = this.workCounter.decrementAndGet();
// If the count has reached zero, all async tasks have finished.
if (tasksLeft == 0) {
// Make activity aware by sending a broadcast.
LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this.ctx);
mgr.sendBroadcast(new Intent("all_tasks_have_finished"));
}
}
}
You should use a CountDownLatch. Here the documentation with examples:
java.util.concurrent.CountDownLatch
Basically you give a reference of CountDownLatch to your threads, and each of them will decrement it when finished:
countDownLatch.countDown();
The main thread will wait on the termination of all threads using:
countDownLatch.await();
First, add this class to your project
public abstract class MultiTaskHandler {
private int mTasksLeft;
private boolean mIsCanceled = false;
public MultiTaskHandler(int numOfTasks) {
mTasksLeft = numOfTasks;
}
protected abstract void onAllTasksCompleted();
public void taskComplete() {
mTasksLeft--;
if (mTasksLeft==0 && !mIsCanceled) {
onAllTasksCompleted();
}
}
public void reset(int numOfTasks) {
mTasksLeft = numOfTasks;
mIsCanceled=false;
}
public void cancel() {
mIsCanceled = true;
}
}
Then:
int totalNumOfTasks = 2; //change this to the number of tasks that you are running
final MultiTaskHandler multiTaskHandler = new MultiTaskHandler(totalNumOfTasks) {
#Override
protected void onAllTasksCompleted() {
//put the code that runs when all the tasks are complete here
}
};
Then in each task - when completed, add the line: multiTaskHandler.taskComplete();
Example:
(new AsyncTask<Void,Void,Void>() {
#Override
protected Void doInBackground(Void... voids) {
// do something...
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
multiTaskHandler.taskComplete();
}
}).execute();
You can use multiTaskHandler.cancel() if you want to cancel the code that runs when all the tasks have completed. For instance - if you have an error (don't forget to also cancel all the other tasks).
* This solution will not pause the main thread!
Another Option could be to store all your new threads in an Array.
Then you could iterate over the Array and wait with thread[i].join for the thread to finish.
see join()
http://developer.android.com/reference/java/lang/Thread.html#Thread(java.lang.Runnable)
When the Iteration is finished all your threads are done and you can work on
RX Merge operator is your friend.
Get rid of AsyncTark is slower than RX and you cannot handle Errors

calling AsyncTask in main thread inside a for loop

I have someclass which do large network operations and it do take some time to complete,and hence i put it in AsyncTask .I have to do this process 'n' times so in the main thread using a for loop i called this asynctask n times.will it throw any error since there is an interrupt in completing the for loop.?
// inside main thread
for(i=0;i<n;i++)
{
new asynctask().execute(new someclass());
}
Running mutliple AsyncTask is not recommended, but if it is few times, then it will work but all async task will run serially not in parallel. But if you want async tasks to run parallelly then you can call it's executeOnExecutor(..) method where you have to pass THREAD_POOL_EXECUTOR as parameter. You can search on google you can find many links. Here is an example for your help.
don't call AsyncTask n times just put your for loop in onPostExecute() and do any task up to n times
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
} catch (Exception e) {
e.printStackTrace();
}
return resp;
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
for(i=0;i<n;i++)
{
//do your operation here
}
}
#Override
protected void onPreExecute() {
// Things to be done before execution of long running operation. For
// example showing ProgessDialog
}
#Override
protected void onProgressUpdate(String... text) {
// Things to be done while execution of long running operation is in
// progress. For example updating ProgessDialog
}
}
}

Categories