i am newbie on android development and i would like to ask how to wait some async tasks that already running. Also when i am trying to sleep the main Thread many of them are suspended by the system. When i use an arraylist to add them and then call to each of them get() many of them never finish on time. Please give me a code example because i searching it over of three days...
Thx!!
for(){
async...
async.execute();
arraylist.add(async);
}
...
for(arraylist.size){
arraylist.get().get();
}
I will try to answer your question here but the question is not clear.
If you want to check whether there is an AsyncTask completed or not in an arraylist, we can use getStatus call that return us a status, and one of the status, luckily, is FINISHED, so you can check your status of any given AsyncTask.
If you want to sleep until one of the AsyncTask is finished, then the best approach probably involves doing something in onPostExecute. When you override it, you can do something to notify the main thread. One of the ways you can do this is here:
public interface Callback {
public void callBack(int id);
}
public class MainActivity implements Callback {
private void function() {
//do your thing
AsyncTask task0 = new MyAsyncTask(this, 0); //implement your own asynctask here,
//with one of the parameters this activity so that you can get a callback.
//Also, optionally give in the id so that you know what index of asynctask is finished first.
//do the same thing for other tasks
task1.execute(params);
}
public void callBack(int id) {
arrayList.get(id).get(); //this is done
}
In your AsyncTask, you simply override the onPostExecute to something like this
protected void onPostExecute (Result result) {
//do your thing
mainActivity.callBack(id);
}
Hope this helps.
Related
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
asyntask.execute();
}
I'm reading data from some API. Is it possible to call doInBackground() from onPostExecute?
I want do it recursively like (network task and update in UI ) for 5 times. Thanks in advance.
Starting the AsyncTask again from inside onPostExecute is a horrible idea. As you want to do it recursively like 5 times for network calls along with UI update, I would like to suggest you to keep an interface to keep track of the AsyncTask call.
So here's an example about how you can achieve the behaviour. You may create an interface like this.
public interface MyResponseListener {
void myResponseReceiver(String result);
}
Now you declare the interface in your AsyncTask class too. So your AsyncTask may look like this.
public class YourAsyncTask extends AsyncTask<Void, Void, String> {
// Declare an interface
public MyResponseListener myResponse;
// Now in your onPostExecute
#Override
protected void onPostExecute(final String result) {
// Send something back to the calling Activity like this to let it know the AsyncTask has finished.
myResponse.myResponseReceiver(result);
}
}
Now you need to implement the interface you've created already in your Activity like this. You need to pass the reference of the interface to the AsyncTask you're starting from your Activity
public class MainActivity extends Activity implements MyResponseListener {
// Your onCreate and other function goes here
// Declare an AsyncTask variable first
private YourAsyncTask mYourAsyncTask;
// Here's a function to start the AsyncTask
private startAsyncTask(){
mYourAsyncTask.myResponse = this;
// Now start the AsyncTask
mYourAsyncTask.execute();
}
// You need to implement the function of your interface
#Override
public void myResponseReceiver(String result) {
if(!result.equals("5")) {
// You need to keep track here how many times the AsyncTask has been executed.
startAsyncTask();
}
}
}
doInBackground() is called before calling onPostExecute.
Since you cannot perform network tasks on the UI thread, an AsyncTask is created.
The AsyncTask executes in the background, performing the network task on the worker thread. Then after the background task is completed, onPostExecute() is called that makes the UI changes on the UI thread.
This should help : https://developer.android.com/reference/android/os/AsyncTask.html
https://developer.android.com/training/basics/network-ops/index.html
The AsyncTask class is used to do some work in background and publish the results to the MainThread so it's generally not possible because the work that's being done in the worker thread may not be doable in MainThread, (like the NetworkOnMainThreadException when you do networking in MainThread).
I suggest you to make an array of your jobs and call the execute() method of your subclass of AsyncTask and it will serialize the jobs to be done in a worker thread.
I am using AsyncTask so that the function I want executes immediately and does not wait till the end to be executed..
but for some reason I don't why it executes in at the end of all process!
I looked at other solutions and found that Thread should be executed at the end but for AsyncTask it should be executed whenever it is called..
here is my code
private void LogMeIn()
{
string CheckValue;
// Here I call the AsyncTask
new GCM().execute(null,null,null);
//gcmRegID is a public variable and should has GCM value assigned to it by now, but I it is empty as GCM() has not been executed yet
//This is always return empty string
CheckValue = gcmRegID;
}
This is the AsyncTask that wait till the end to be executed
//This is the AsyncTask
private class GCM extends AsyncTask<String, String, String> {
private String resp;
private Context context;
#Override
protected String doInBackground(String... params) {
GCMHelper gcmRegistrationHelper = new GCMHelper (
getApplicationContext());
try {
gcmRegID = gcmRegistrationHelper.GCMRegister("123456789");
} catch (Exception e) {
e.printStackTrace();
}
return gcmRegID;
}
}
I tried to put the call for GCMRegister in onPreExecute but i get an error that it has to be in the main thread
it is like i am going in circles....
the call has to be in the main thread and the main thread will be executed at the end of the function...
it is like no way to get the GCM code in the middle!!!!
How can I make this AsyncTask executes when it called??
Thanks
Without seeing more of your code it's hard for me to tell but I would take a look at where you are calling LogMeIn(). Because your AsyncTask and call to execute are nested in the LogMeIn() function, it won't be called until LogMeIn() is first called.
AsyncTask goes through the following 4 steps in order after calling execute():
onPreExecute()
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
These can be added to your GCM class and used however you like. Note that you don't call them directly. AsyncTask does it automatically after calling .execute().
Only the tasks specified in doInBackground(Params...) are executed on a background thread. The rest are all done on the UI(or main) thread. I would suggest putting either a toast or a log inside onPreExecute() and in onPostExecute() to debug where/when GCM().execute is actually being called and then to tell you when the background task is complete. This will give you a better idea of what is going on.
Make sure you aren't trying to update the UI in doInBackground().
Would love to help more but we would need to see more of your code.
#Override
public void onPreExecute() {
super.onPreExecute();
Log.d("GCM", "onPreExecute: called");
}
#Override
public void onPostExecute(String resultOfDoInBackground) {
super.onPostExecute(resultOfDoInBackground);
Log.d("GCM", "onPostExecute: called");
}
AsyncTask keeps a queue of tasks and a thread pool,the thread pool execute the tasks one by one,so if you have too more tasks ,you will find it not execute your tasks immediately.
And in one process ,all your AsyncTask share one thread pool.In this case,you should make one task queue by yourself,you can just use HandleThread to execute a timely task.
Try placing your new GCM().execute(null,null,null); in the protected void onCreate(Bundle savedInstanceState) method. this way it will be called once the app is ran. This way you will have your GCM id before you get to the LogMEIn method.
Try this -
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new GCM().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params);
} else {
new GCM().execute();
}
If I did something like this:
public class MyFragment extends Fragment
{
private GetDataTask mGDT;
//onCreate() and onCreateView() are implied here
public void runTasks()
{
new TaskOne().execute();
new TaskTwo().execute();
new TaskThree().execute();
}
public class GetDataTask extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... params)
{
runTasks();
}
}
#Override
public void onResume()
{
super.onResume();
mGDT = new GetDataTask();
mGDT.execute();
}
#Override
public void onDestroy()
{
super.onDestroy();
mGDT.cancel(true);
}
}
Would calling mGDT.cancel(true) in onDestroy() end the individual AsyncTasks running in runTasks()? What is the best way to achieve something like this? I have multiple bots that will be gathering data from the web and I want each one on its own thread and I need to be able to cancel all of them if the fragment or activity is destroyed. I'm new to Android programming and multithreading so I'm not familiar with the best ways to do this type of multithreading.
That's complicated.cancel() interrupts the thread that's running (the thread that will run doInBackgroundImpl()). If the outer task's doInBackgroundImpl() hasn't run yet, it won't run. However, if it's already run or in the middle of running, it's going to run unless you explicitly look for the interrupted flag,
#Override
protected Void doInBackground(Void... params)
{
if (!Thread.isInterrupted()) {
runTasks();
}
}
And of course if the code execution of the thread has already passed the conditional interrupted check, it's going to call runTasks().
Now, if runTasks() does execute(), canceling the outer task won't effect the execution of the inner tasks. Once they are executed, they are placed on AsyncTask's executor queue and will be executed when previous task is completed (or right away if the queue is empty).
Takeaways,
1) Each executed task is independent. There's no notion of a subthread or anything like that. You have to explicitly cancel each task. The fact that one task is started by another task has no bearing on the semantics of cancel().
2) You simply can't stop a thread cold. It's why Thread.stop() is deprecated since Java 1.2 or something. All you can do is mark it interrupted, then either hope the code you use in the thread respects isInterrupted(), or write your own code to respect it.
In your case, if your goal is to cancel all subtasks when the parent task is canceled, you can do something like,
#Override
public void cancel(boolean interrupt) {
super.cancel(interrupt);
task1.cancel(interrupt);
task2.cancel(interrupt);
...
}
I've a method who return a result (return an integer), my method is executed in a Thread for load 40 000 objects, i return an integer who count the number objects loaded. My question is, How return the int with the Thread ? Actually, the result is returned directly and is equal to 0.
public int ajouter(params) throws DaoException, ConnectException {
final ProgressDialog dialog = ProgressDialog.show(mActivity, "Title",
"Message", true);
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dialog.dismiss();
}
};
Thread t = new Thread() {
public void run() {
try {
Str_Requete = "SELECT * FROM Mytable";
ResultSet result = ExecuteQuery(Str_Base, Str_Requete);
Index = addObjects(result);
handler.sendEmptyMessage(0);
} catch (SQLException e) {
e.printStackTrace();
}
}
};
t.start();
return Index;
}
When i call my method in my mainActivity :
int test = myObjs.ajouter(params);
test is equal to 0, the value is returned directly...
My constraint is didnt use AsyncTask.
The whole point of using a Thread is not to block the calling code while performing the task of the thread. Thread.start() returns immediately, but in the meantime a new thread is started in parallel to the current thread which will execute the code in the run() method.
So by definition there is no such thing as returning a value from a thread execution. You have to somehow send a signal back from the thread that performed the task to the thread in which you need the result. There are many ways of doing this, there's the standard Java wait/notify methods, there is the Java concurrency library etc.
Since this is Android, and I assume your calling code is running on the main thread, it's probably wise to use the functionality of Handler. And in fact, you are already doing that - you have a Handler that closes the dialog when the thread is done with its work - but for some reason you seem to expect the result of that work to be ready before it has even started. It would be reasonable to extend your existing Handler with some code that does something with the calculated value and remove the code that returns the value of a variable before or at the same time as it's being calculated by another thread.
I also strongly encourage you to study some concurrency tutorial such as Oracle's concurrency lesson or Android Thread guidelines to really understand what's going on in the background. Writing concurrent code without mastering the concepts is bound to fail sooner or later, because it's in the nature of concurrency that multiple things are happening at the same time, will finish in random order etc. It may not fail often, but you will go crazy wondering why something that works 90% of the time suddenly fails. That's why topics such as atomicity, thread synchronization etc are critical to comprehend.
Edit: Simple Android example of starting a worker thread, performing some work, posting back event to main thread.
public class MyActivity extends Activity {
private Handler mHandler = new Handler();
...
private void doSomeWorkInBackground() {
new Thread() {
public void run() {
// do slow work, this may be blocking
mHandler.post(new Runnable() {
public void run() {
// this code will run on main thread,
// updating your UI or whatever you need.
// Hence, code here must NOT be blocking.
}
});
}
}.start();
// This code will be executed immediately on the main thread, and main thread will not be blocked
}
You could in this example also use Activity.runOnUiThread(Runnable).
Please consider however that AsyncTask basically wraps this kind of functionality in a very convenient way, so if it suits your purposes you should consider using AsyncTask.
If you dont want to use AsyncTask or ForkJoin, then you could implement an Interface e.g. callback in your main class.
In your Example you dont wait until the Thread is done... thread.join
One Solution:
Your Thread is a extra class with an constructor to hold the reference to the calling class.
public Interface callback
{
public int done();
}
public class main implements callback
{
...
CustomThread t = new CustomThread(this)
...
}
public class CustomThread extends Thread
{
private Callback cb;
public CustomThread(Callback cb)
{
this.cb=cb;
}
.
.
.
//when done
cb.done(int)
}
I have been browsing about this I am not finding the answer that suits my problem. But i would like on execute onPostExecute but it never gets called.
I send in a timestamp, unixtime, to the server and I get a list in return (ArrayList). Then I want to work with that list in onPostExecute. I do get the list though.
I send in Long
I want to work with that list, I think.
I want to return that list
Thats why I do 'Long, ArrayList, ArrayList'
Could use a little help, thanks!
private class getMealsByDayConnection extends AsyncTask<Long, ArrayList<CalanderMeal>, ArrayList<CalanderMeal>> {
protected ArrayList<CalanderMeal> doInBackground(Long... params) {
CalendarService service = CalendarServiceFactory.getCalanderService();
try {
return service.getMealsByDay(params[0]);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ArrayList<CalanderMeal> result){
CalendarAdapter adapter = null;
adapter.notifyDataSetChanged();
}
}
According to the documentation, the method will not be called if the task is cancelled. So perhaps your task is being cancelled since an empty list is returned? Or the onPostExecute(result) doesn't work because result is an empty list? You might be able to catch this by overriding onCancel().
Btw, you did call the async task from within the main UI thread and start the task with the getMealsByDayConnection.execute() method, right?
i think you are calling asyncTask with
getMealsByDayConnection.doInBackground(params);
if you are executing like this , task will execute in main thread and the doInBackground() function alone will execute.
you should execute asynctask like this,
getMealsByDayConnection.execute();