I am having trouble working with asynctasks. The problem is that I need data from one asynctask to be loaded into a static variable before another asynctask begins since asynctask2 needs that static variable. I tried using this code to stall asynctask2 but it doesn't even show up in my log cat:
//geocode is the first asynctask
while(geocode.getStatus().equals(android.os.AsyncTask.Status.PENDING))
{try {;
wait(100);
Log.i("waiting", "waiting");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
use the onPostExecute of the first AsyncTask to start the next one, that way you know it has finished and it is safe to start the next one. I would however try to think of a better way to accomplish what you are trying to do
Related
I have an AsyncTask, and in its doInBackground method I call a method in another class:
#Override
protected ArrayList<CustomClass> doInBackground(ArrayList<CustomClass>... array) {
ArrayList<CustomClass> retorno= DataNetwork.GetCustomClassArrayList(array[0],(...more parameters...));
return retorno;
}
In DataNetwork I have that method, which does a REST call, and returns a result. I am forced to use a library that makes the REST call (I think it uses Volley, but I am not sure. To call this library, I have to make an Intent, which is passed to the method makeRESTCall):
public static ArrayList<CustomClass> GetCustomClassArrayList(various params goes here){
ArrayList<CustomClass> toReturn;
//some parameters processing
library.makeRESTCall(Intent intent){
//processing the answer
toReturn=processAnswerJSONResponse();
}
return toReturn;
}
This way, I get to the return toReturn line, before answer from REST is processed. So, I tried to make a Thread, and use the join statement. The GetCustomClassArrayList method (well, most of it, until the t.start()) is now inside a Thread. The end of the method is now:
(...)
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return toReturn;
The execution calls t.join() immediately after t.start(); and toReturn is null.
Maybe is a noob question, but using the method join() always worked for me, and waited for the thread to finish before entering the return statement. No exception, no error. It just doesn't wait for the thread to finish.
Why is not working now? What can I do to wait for the toReturn variable to be fulfilled before entering the return statement?
Thank you.
The problem likely stems from using a library which is already returning the response asynchronously, so your AsyncTask is not blocking. Check the library documentation.
AsyncTask is not like a normal thread. It is specialized to execute one time, blocking if necessary in the doInBackground method, then returning results to be handled in the main thread. If your 3rd party REST library has a synchronous version of it's calls, you could use that in your AsyncTask, but it will likely be less efficient than the library's built in functionality.
Can someone please explain to me the proper usage of try/catch when accessing an Android database? Android Studio forces you to use it whenever you are opening a database for writing. I understanding the purpose of using it but my question is would it better do include all of my database work in the try clause like this?
try {
db.open();
db.delete(item);
db.add(item);
/////......
} catch (SQLException e) {
e.printStackTrace();
}
db.close()
Or is it better to use it like this?
try {
db.open();
} catch (SQLException e) {
e.printStackTrace();
}
db.delete(item);
db.add(item);
/////......
db.close()
Is there an important difference? Is one way more efficient or safer than the other?
Thanks in advance for your responses!
Look at the documentation and only use try / catch on methods that throw exceptions
You use the catch block to actually catch exceptions which can be thrown from your code (during runtime). So every call which can throw an exception should be tried/catched, because it helps you differentiating, what went wrong with your code.
So: Wrap a try catch around every function call which can throw an exception
in your second example, if your delete query is malformed, you won't know, the program will continue to run thinking it's been successful.
A try catch, tries something, then catches any errors which may arise.
With reference to the following code.
for (Future<Long> future : list) {
try {
sum += future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Now when i call future.get will this be blocking call? So if i am executing this on the Main Thread of and android application will this cause an ANR exception ? I notice the Interrupted exception is also thrown, so does this mean their is a sleep called on the thread in the get function ?
Yes, documentation of Future.get() says:
Waits if necessary for the computation to complete, and then retrieves its result.
so, it will block until results of computation are available, or the computation was interrupted (cancelled or resulting in exception).
It may cause ANR if your computations take long time to finish.
Again, from documentation of Future.get():
#throws InterruptedException if the current thread was interrupted while waiting
Now, since you call Future.get() from main thread, I suspect that it is the Android system which interrupts your main thread in an attempt to make it responsive again. But it may also be caused by another thread of your application - it's hard to tell, since you haven't specified what your application does, what threads does it create, when, do you use ExecutorService (and if so, which implementation), and so on.
No, FutureTask.get() (which I believe is the implementation of Future you're using) does not call Thread.sleep(). Instead, putting the thread in waiting mode is done via thread parking which causes it to not be scheduled for execution until a signal is given. This may cause in ANR error if done in the main thread. For details of parking mechanism consider reading documentation and this question
You can simply check if future "is done" by calling future.isDone(). Code example:
String result = "";
if (myFuture.isDone()) result = (String) myFuture.get();
You will probably want to check it in an endless loop.
Beware of deadlock with future.get(). If both the MainThread, that call future.get(), and the WorkerThread is synchronized (on the same object) then you get a deadlock.
On rare occasion, I'm getting this mysterious RuntimeException in one of my AsyncTasks. I have multiple places where I implement AsyncTasks in my app, but no matter how much I dig into these errors I can't seem to get any info about why this RuntimeException is being thrown or what thread it is happening in. Based upon the "completedAbruptly=true" I'm guessing that there's an uncaught exception in the async task, but I don't even know where to begin to try to figure out where... ideas? Thanks!
completedAbruptly=true happens when the executed task throws an exception. And the task of an AsyncTask is executing the doInBackground method.
I suggest you wrap your doInBackground code into a try/catch block and let it print exceptions that occur.
protected Void doInBackground(Void... params) {
try {
// ----------
// do stuff
return null;
// ----------
} catch (Throwable t) {
Log.e("AsyncTask", "OMGCrash", t);
// maybe throw it again
throw new RuntimeException(t);
}
}
That should show you the reason all this happens.
According to the source code, completedAbruptly is a sign that the thread finished due to user interaction. I would guess that the exception happens when an activity is finished before the async task completes. It should be trivial to discard this possibility: just replace one of your AsyncTasks with an infinite loop and press "back" on the emulator.
I am implementing a testcase in Android Juint. I am facing problem in
handling threads. After the successful running of a test case, it will
not wait for child thread to be finished. e.g. If one testcase call
some services in server. testcase will successfully send request to a
server, but it will not wait for a response. Because testcase will
start this request in a different Thread. Currently I am using
following code,
currentThread = Thread.currentThread();
synchronized (Thread.currentThread()) {
try {
Thread.currentThread().wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
After getting response I am using the following code to start the
current thread again.
currentThread.interrupt();
I think this is not the good way to do it. There must be a some other
technique to handle this problem properly. Please let me know as soon
as possible if any one knows solution for this.
Thanks,
Vashishta
In your code the synchronized block never blocks (wait for another thread), because you synchronize on Thread.currentThread() which is a different object in different threads.
You have so synchronize on an object common to all threads: typically an object that contains shared data. Then you synchronize{..} a block od code that manipulates this data.