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;
}
Related
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.
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);
}
}
I want to make downloader, which download data and then call function in UI thread. I have this in main activity
onCreate(){
...
dataRepository.downloadIfNewOrEmpty(new DownloadResponse() {
#Override
public void SuccessResponse(Response response) {
// do something in UI
}
});
}
My function downloadIfNewOrEmpty looks for now only simple with sleep()
public void downloadIfNewOrEmpty(final DownloadResponse response){
//final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
response.SuccessResponse(ResponseCode.SUCCESS);
/*handler.post(new Runnable() {
#Override
public void run() {
response.SuccessResponse(ResponseCode.SUCCESS);
}
});*/
}catch (Exception e){
// Log...
}
}
}).start();
}
If I run this code, it normally does the job and update my UI. I found this solution with Handler (android.os.Handler) but if I run it without or with Handler (commented version) it works same.
Although without handler function SuccessResponse is run in UI thread?
Thank you
Although without handler function SuccessResponse is run in UI thread?
Yes, because response is instance of DownloadResponse which is passed from UI Thread as parameter to downloadIfNewOrEmpty.
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
}
}
}
Say I have a class call MyTask
Every time I new a object for MyTask, it will create a thread
boolean mContinueThread = true;
public MyTask (Activity activity) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (mContinueThread) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
});
thread.start();
return null;
};
}.execute();
}
At first I new myTask1, myTask2, myTask3 then add to the List
List<MyTask> myTasks = new ArrayList<MyTask>;
myTasks.add(myTask1);
myTasks.add(myTask2);
myTasks.add(myTask3);
Now there should be 3 threads run on the background, then I renew the by
myTasks = new ArrayList<MyTask>;
And looks like those threads in myTask1, myTask2, myTask3 are still running, the finalize never get called. I know I can set mContinueThread as true for each MyTask objects before I renew the list, but I would like to know is there any way (callback?) I can know those MyTask objects are not no longer in the list and then set mContinueThread as false?
public MyTask (Activity activity) {
...
#Override
protected void finalize() throws Throwable {
mContinueThread = false;
super.finalize();
}
It seems redundant to have an async task which just starts a Thread.You can achieve the desired outcome, by puting the contance of the thread directly into you AsyncTask$doInBackground()
You can call the call the AsyncTask$cancel(boolean mayInterrupt) method, this will rise an InterruptedException, the only thing left to do, is adding a return statement within the catch:
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// cancel was called
return null;
}
return null;
};
Cancel the task like that:
myTasks.get(i).cancel(true);
Don't forget to pass true or it won't work
you have to have a variable for your AsyncTask first, so that you can call:
myTasks.get(0).getMyAsyncTask().cancel(boolean);
As you can see here, it is not that easy to cancel an AsyncTask. After you call cancel(boolean), it will: (from docs:
invoking this method will cause subsequent call to isCancelled() to
return true. onCancelled(Object) will be invoked after doInBackground
instead of onPostxecute. To ensure that a task is cancelled, you
should always check the return value of isCancelled from
doInBackground.
So, you call cancel(booelan) onto your reference variable of your AsyncTask and in doInBackground, you always check for isCancelled() in order to stop some processes in your doInBackground method.
You should handle your doInBackground method manually in order to stop all the executions there. So if you have while(true){ do_something }, then it should become while(true){ if(!isCancelled()) { do_something } }