Block until Loader finishes in ActivityInstrumentationTestCase2 - android

I am writing an Android Activity test case by extending ActivityInstrumentationTestCase2. The Activity I am testing offloads work to a Loader. The Activity itself is the LoaderCallback.
The problem is that the test case finishes before the Loader completes its work (because the Loader is obviously running on another thread than the test case). How can I get the test case to wait until the Loader has finished its work.
One thought I had was to join to the underlying Loader thread. However, I can't seem to find a way to get access to the underlying thread. Also, the Loader thread might not start immediately so not sure this is the right approach.
The other though I had was to register a LoaderListener in the test case, but it seems a particular Loader can only have one LoaderListener.

You could set a max timeout. Check for a null value in the loader every so often until you reach the max timeout. Once the max timeout is set have the test fail because the loader would not load.

Try to do it with mutex or ReentrantLock.

You need to use some Java synchronization method between the thread the test case is running in, and the background thread or action you are waiting to complete.
I have used a countdown latch.
In your code under test (Activity in my case)
Initialize it when your activity is created
private final CountDownLatch signal = new CountDownLatch(1);
When the Loader finishes, have your code signal it's done:
signal.countDown();
I provide a getter for the latch in my code under test
public CountDownLatch getSignal() {
return signal;
}
In your test:
start the activity (which starts the background thread)
MainActivity activity = getActivity();
get the latch to wait on
CountDownLatch signal = activity.getSignal();
do other stuff, then wait for the background task to end
if (!signal.await(30, TimeUnit.SECONDS)) {
fail("Timed out waiting for the background task to complete");
}
This works for stuff being in done in background threads, AsyncTasks etc that are started by the onCreate() method of your activity...

Related

How to make synchronous network call in android?

I am trying to make an application that constantly hits the google API to fetch the distance between two points and then process the distance and add it in db inside a loop.
I was previously using the volley but it does not waits and my function proceeds with the rest of lines of code. I need help so that the line of code waits for that method to return only if some result is received once I hit google API, then use that result in next line of code.
I'd recommend looking into coroutines. More specifically take a look at the async launcher which should return the value to an awaiting variable. Your code runs asynchronously (starting a new thread so your main UI thread doesn't block and the user can freely do as they wish) and when the call returns your code is called once again at the point where the variable will be awaiting. You could set a timer right before starting the async call and stop it after await.
You could also use withContext{} to await for a result. The code will be continued in the calling function when the coroutine returns a result.
startTimer()
val job = coroutineScope{
async{
networkCall()
}
}
job.await()
stopTimer()
or
startTimer()
coroutineScope{
launch{
withContext{
networkCall()
}
//code will continue when networkCall() has returned a result
stopTimer() //be careful, this may be called through a background thread.
}
}
Coroutines are thread-safe and lightweight so you can start as many as you want without any problems. Also, by using coroutineScope you will avoid lifecycle problems like your ui being rotated which would normally cause a network call to be resent. With coroutineScope your call will have the life span of the calling activity/fragment thus it will be cancelled or killed if your app unexpectedly decides to stop and not care for the result any longer.
Hope this helped, Panos.
If you are beginner use retrofit library to make API calls in there is option enque will call API background for you.
https://www.journaldev.com/13639/retrofit-android-example-tutorial
If you are pro go for Rxjava with Retrofit.
https://medium.com/3xplore/handling-api-calls-using-retrofit-2-and-rxjava-2-1871c891b6ae
You cannot do synchronous calls on the main thread. Blocking the UI thread on a network call for more than a specified period of time would trigger an ANR.
A couple of options would be to use an AysncTask or AsyncTaskLoader. Blocking the main thread is definitely not recommended.
AsyncTasks create a separate thread of execution while the UI thread can continue with its work.
Android applications usually start with a single thread of execution so if you block this thread then an ANR would result.
Take a look here
If you don't mind the ANRs which will not be acceptable to a user then go with using a simple HttpURLConnection but this is not recommended.
If you do not prefer the AsyncTask approach you can create a Runnable to do the background processing and then update the UI thread.
More here
You can implement a jobservice to get distance in an interval.You can view the implementation .here

Android Instrumentation testing an AsyncTask

I am new to instrumentation testing in Android. Can someone show me how i can start an async task and wait for the result to be computed ? Many of my network calls rely on AsynTasks and i need to know how we can test it ? For activities we have a getInstrumentation().waitForMonitor , what can we do for AsyncTasks ?
The AsyncTask class has a blocking get() method that will basically wait for the task to finish before it returns. It's the synchronous version of calling execute(), which means you could think of it as the background work being executed on the main thread - hence it blocks until finished.
public final Result get ()
Waits if necessary for the computation to complete, and then retrieves
its result.

If I start an AsyncTask during onCreate, when will it begin execution?

I want to ensure that I don't slow down my app's startup time and need to start a background task that's unrelated to user input--for instance, filling a cache.
If I start an AsyncTask from my onCreate method, when will the doInBackground method actually begin to execute? (Assume a single core device)
Is it possible that Android could schedule it before onCreate/onResume has completed, or is it smart enough to recognize that the background thread shouldn't run until the UI thread is completely finished?
If you look at AsyncTask source code you will see that it is just using ThreadPoolExecutor or serial executor for running tasks. Default internal behavior depends on Android version (from AsyncTask docs):
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
But anyway doInBackground execution is not connected with Activity lifecycle so AsyncTask may be executed at almost any time. This depends only on how many tasks you have already started, on default Executor which is used by AsyncTask and on thread scheduler.
I usually use AsyncTasks in onCreate() like this:
private MySuperSpecialTask mySuperSpecialTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(...);
// [...]
mySuperSpecialTask = new MySuperSpecialTask();
mySuperSpecialTask.execute();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mySuperSpecialTask != null) {
mySuperSpecialTask.cancel(true);
}
}
This makes sure that everything is initialized before the task gets started.
actually strictly speaking there is no execution order of your UI code and starting the asynctask I found out. Normally one does not experience this, however, if your UI thread takes longer for some reason, eg waiting for external input etc, the asynctask might have gotten started BEFORE UI code has finished.
Writing UI code is just a request to the Android system and this waits in the execution loop. So if asynctask starts before that because there are enough ressources (or as mentioned UI thread is delayed for whatever reason) there is no execution order guarantee.
One easy way to enforce this is - in case you don't mind and you can be sure that it is suffiencient - delay the starting of the asynctask with ScheduledExecutorService or a "cleaner" way would be to implement some kind of gate keeper that waits for a flag to be set to true and then start the asynctask. Or you may even have a while-loop at the beginning of your asynctask that waits for the flag to be set to true, like in many communication situations with external devices.
The flag would be set to true AFTER you can be (normally) sure that your UI has finished.

How to make a new instance of a Thread? [duplicate]

I am having a real hard time finding a way to start, stop, and restart a thread in Java.
Specifically, I have a class Task (currently implements Runnable) in a file Task.java. My main application needs to be able to START this task on a thread, STOP (kill) the thread when it needs to, and sometimes KILL & RESTART the thread...
My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow() any future call to .execute() fails because the ExecutorService is "shutdown"...
So, how could I accomplish this?
Once a thread stops you cannot restart it. However, there is nothing stopping you from creating and starting a new thread.
Option 1: Create a new thread rather than trying to restart.
Option 2: Instead of letting the thread stop, have it wait and then when it receives notification you can allow it to do work again. This way the thread never stops and will never need to be restarted.
Edit based on comment:
To "kill" the thread you can do something like the following.
yourThread.setIsTerminating(true); // tell the thread to stop
yourThread.join(); // wait for the thread to stop
Review java.lang.Thread.
To start or restart (once a thread is stopped, you can't restart that same thread, but it doesn't matter; just create a new Thread instance):
// Create your Runnable instance
Task task = new Task(...);
// Start a thread and run your Runnable
Thread t = new Thread(task);
To stop it, have a method on your Task instance that sets a flag to tell the run method to exit; returning from run exits the thread. If your calling code needs to know the thread really has stopped before it returns, you can use join:
// Tell Task to stop
task.setStopFlag(true);
// Wait for it to do so
t.join();
Regarding restarting: Even though a Thread can't be restarted, you can reuse your Runnable instance with a new thread if it has state and such you want to keep; that comes to the same thing. Just make sure your Runnable is designed to allow multiple calls to run.
It is impossible to terminate a thread unless the code running in that thread checks for and allows termination.
You said: "Sadly I must kill/restart it ... I don't have complete control over the contents of the thread and for my situation it requires a restart"
If the contents of the thread does not allow for termination of its exectuion then you can not terminate that thread.
In your post you said: "My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow()..."
If you look at the source of "shutdownnow" it just runs through and interrupts the currently running threads. This will not stop their execution unless the code in those threads checks to see if it has been ineterrupted and, if so, stops execution itself. So shutdownnow is probably not doing what you think.
Let me illustrate what I mean when I say that the contents of the thread must allow for that thread to be terminated:
myExecutor.execute(new Runnable() {
public void run() {
while (true) {
System.out.println("running");
}
}
});
myExecutor.shutdownnow();
That thread will continue to run forever, even though shutdownnow was called, because it never checks to see if it has been terminated or not. This thread, however, will shut down:
myExecutor.execute(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
System.out.println("running");
}
}
});
myExecutor.shutdownnow();
Since this thread checks to see whether or not it has been interrupted / shut down / terminated.
So if you want a thread that you can shut down, you need to make sure it checks to see if it has been interrupted. If you want a thread that you can "shut down" and "restart" you can make a runnable that can take new tasks as was mentioned before.
Why can you not shut down a running thread? Well I actually lied, you can call "yourThread.stop()" but why is this a bad idea? The thread could be in a synchronized (or other critical section, but we will limit ourselves to setions guarded by the syncrhonized key word here) section of code when you stop it. synch blocks are supposed to be executed in their entirity and only by one thread before being accessed by some other thread. If you stop a thread in the middle of a synch block, the protection put into place by the synch block is invalidated and your program will get into an unknown state. Developers make put stuff in synch blocks to keep things in synch, if you use threadInstance.stop() you destroy the meaning of synchronize, what the developer of that code was trying to accomplish and how the developer of that code expected his synchronized blocks to behave.
You can't restart a thread so your best option is to save the current state of the object at the time the thread was stopped and when operations need to continue on that object you can recreate that object using the saved and then start the new thread.
These two articles Swing Worker and Concurrency may help you determine the best solution for your problem.
As stated by Taylor L, you can't just "stop" a thread (by calling a simple method) due to the fact that it could leave your system in an unstable state as the external calling thread may not know what is going on inside your thread.
With this said, the best way to "stop" a thread is to have the thread keep an eye on itself and to have it know and understand when it should stop.
If your task is performing some kind of action in a loop there is a way to pause/restart processing, but I think it would have to be outside what the Thread API currently offers. If its a single shot process I am not aware of any way to suspend/restart without running into API that has been deprecated or is no longer allowed.
As for looped processes, the easiest way I could think of is that the code that spawns the Task instantiates a ReentrantLock and passes it to the task, as well as keeping a reference itself. Every time the Task enters its loop it attempts a lock on the ReentrantLock instance and when the loop completes it should unlock. You may want to encapsulate all this try/finally, making sure you let go of the lock at the end of the loop, even if an exception is thrown.
If you want to pause the task simply attempt a lock from the main code (since you kept a reference handy). What this will do is wait for the loop to complete and not let it start another iteration (since the main thread is holding a lock). To restart the thread simply unlock from the main code, this will allow the task to resume its loops.
To permanently stop the thread I would use the normal API or leave a flag in the Task and a setter for the flag (something like stopImmediately). When the loop encountered a true value for this flag it stops processing and completes the run method.
Sometimes if a Thread was started and it loaded a downside dynamic class which is processing with lots of Thread/currentThread sleep while ignoring interrupted Exception catch(es), one interrupt might not be enough to completely exit execution.
In that case, we can supply these loop-based interrupts:
while(th.isAlive()){
log.trace("Still processing Internally; Sending Interrupt;");
th.interrupt();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
There's a difference between pausing a thread and stopping/killing it. If stopping for you mean killing the thread, then a restart simply means creating a new thread and launching.
There are methods for killing threads from a different thread (e.g., your spawner), but they are unsafe in general. It might be safer if your thread constantly checks some flag to see if it should continue (I assume there is some loop in your thread), and have the external "controller" change the state of that flag.
You can see a little more in:
http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
May I ask why you want to kill the thread and restart it? Why not just have it wait until its services are needed again? Java has synchronization mechanisms exactly for that purpose. The thread will be sleeping until the controller notifies it to continue executing.
You can start a thread like:
Thread thread=new Thread(new Runnable() {
#Override
public void run() {
try {
//Do you task
}catch (Exception ex){
ex.printStackTrace();}
}
});
thread.start();
To stop a Thread:
thread.join();//it will kill you thread
//if you want to know whether your thread is alive or dead you can use
System.out.println("Thread is "+thread.isAlive());
Its advisable to create a new thread rather than restarting it.

Android: Properly destroying asyncTask?

I'm currently using asyncTask() to do some background exchanging of bitmap images as my activity progresses, and all works just fine; until I end the activity where the task resides. The task's thread goes into "wait" status instead of being destroyed? I've cancelled, and checked the return value of .isCancelled() as well. This wouldn't really be a problem except when I restart my activity again from a MAIN activity it will actually make a new thread for the new asyncTask(); thus leaving the old one sitting there "waiting" in the background? Is this a bug, or am I simply using this feature incorrectly?
AsyncTask uses a thread pool. It is normal for you to see 4/5 async tasks in your debug panel. Just make sure that your async tasks do not hold strong references to the activity (try to make those async tasks static inner classes (or event separate classes) and have them hold a WeakReference to the activity instead of a strong reference.
Background task, progress dialog, orientation change - is there any 100% working solution?
AsyncTask threads never die
Simple Thread Management - Java - Android
etc. > Try to search "android asynctask thread pool" to learn more.
i think you should use static flag variable in your doInBackground function for terminating operation or loop. In that way you can achieve your task

Categories

Resources