AsyncTask source code questions - java

I was reading AsyncTask.java and there are few places that I can't understand.
What does this code actually do? Judging by the comment it should create the handler, but I can't get how it can do this. The method getLooper() in the Handler class just returns the handler, so there is no way I can see it can initialize a new handler.
/** #hide Used to force static handler to be created. */
public static void init() {
sHandler.getLooper();
}
Why putting postResultIfNotInvoked() in the overriden done() method? How can it be not invoked? If I understand this right, first the call() method of mWorker will be called and then mTaskInvoked is guaranteed to be true.
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
//...
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
#Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};

init() isn't really used in regular code.
It can be used in platform test code - calling it first makes the class loader initialize the static members on the current thread. It's useful to making sure the Handler is created on the main UI thread while tests run on a background thread for example.
Because of #hide, it's not usable in code written with SDK's stub version of android.jar.
This is there to fix a bug to make sure onCancelled() is called if cancel() is called early.

Related

SwingWorker's done() method unexpected behaviour on disposing JDialog

I have a SwingWorker class whose doInBackground executes queries on a remote database. I invoke publish(true) which sets setVisible to true for the JDialog holding a loader animation.
Everything is working fine as expected:
Background method starts.
JDialog modal is shown.
Background method completes.
JDialog is hidden/disposed in done() method.
UI is updated with database values.
However, when I point my application to the database running on my local machine the JDialog is shown but never closed/disposed even though the done() was called. This halts execution of UI code in the done method as well not until I manually close the loader dialog.
This odd behaviour is as follows:
Background method starts.
JDialog modal is shown.
Background method completes.
JDialog is NOT hidden/disposed in done() method.
UI is NOT updated
I must mention that execution over the remote database takes 10 seconds or more but a split second on my local database. How is the faster speed causing this odd behaviour?
Below is my code snippet:
new SwingWorker<Void, Boolean>() {
JDialog loader = new MyDialogLoader();
#Override
protected Void doInBackground() {
publish(true);
//DATABASE EXECUTION CODE IS HERE
publish(false);
return null;
}
#Override
protected void process(List<Boolean> chunks) {
for (Boolean val : chunks) {
loader.setVisible(val);
}
}
#Override
protected void done() {
loader.dispose();
//UI UPDATE WITH DATABASE VALUES CODE HERE;
}
}.execute();
Probably there is an Exception being thrown in doBackground(), so publish(false) is not being executed. Maybe an error accessing the database...
The Exceptions thrown by doBackground are silently caught and saved by the SwingWorker. The way to check if such an Exception was thrown, is to call the get() method in the done() method. It will throw an ExecutionException having the original exception as cause:
#Override
protected void done() {
loader.dispose();
try {
get();
} catch (ExecutionException ex) {
ex.printStackTrace();
// some message or what ever using ex.getCause()
} catch (InterruptedException ex) {
ex.printStackTrace();
// TODO
}
//UI UPDATE WITH DATABASE VALUES CODE HERE;
}
I am sharing this as the answer because it has solved the issue.
I did away with publish and process methods; the loader JDialog is now made visible from doInBackground. To ensure this UI interaction is performed on the Event Dispatch Thread, the statement is placed inside SwingUtilities.invokeLater.
new SwingWorker<Void, Void>() {
JDialog loader = new MyDialogLoader();
#Override
protected Void doInBackground() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
loader.setVisible(true);
} catch (Exception e) {
e.printStackTrace()
}
}
});
//DATABASE EXECUTION CODE IS HERE
return null;
}
#Override
protected void done() {
loader.dispose();
//UI UPDATE WITH DATABASE VALUES CODE HERE;
}
}.execute();

Mockito verify fails in second unit test

I am using Mockito together to JUnit to implement unit tests for a class in an Android project.The problem is that I call Mockito.verify in two consequent tests where the tests are exactly same (to make sure that I am using Mockito correctly) but the interesting thing is that verify in second test always fails.I suspect that some operations need to be done before each test using #before annotation or so, that I have missed.Here are some code snippet about what I am doing.
I use Android Studio 3.4.1, Mockito 2.7.22 and JUnit 4.12.
#Test
public void test_onStart_do_nothing() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
verify(mockedZConnection, times(1)).connect();
}
#Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Line above is the line that error message points to!
verify(mockedZConnection, times(1)).connect();
}
Here comes the function under test
public void initConnection(ZConnection connection) {
Log.d(TAG,"initConnection()");
if (mConnection == null) {
mConnection = connection;
}
if (!mActive) {
mActive = true;
if (mThread == null || !mThread.isAlive()) {
mThread = new Thread(new Runnable() {
#Override
public void run() {
// The code here runs in a background thread.
Looper.prepare();
mTHandler = new Handler();
try {
mConnection.connect();
} catch (IOException e) {
Intent i = null;
i = new Intent(ZConnectionService.UI_NOTCONNECTED);
i.setPackage(getApplicationContext().getPackageName());
getApplicationContext().sendBroadcast(i);
e.printStackTrace();
// Stop the services all together.
stopSelf();
}
Looper.loop();
}
});
mThread.start();
}
}
}
I expect that both tests should pass without any problem. In fact, both tests are passed when I ran them individually, but they fail when I run the whole suite and the error is:
Wanted but not invoked:
mockedZinkConnection.connect();
-> at com.app.z.ZConnectionServiceUnitTest.test_onStart_throw_IO_exceptioon(ZConnectionServiceUnitTest.java:207)
Actually, there were zero interactions with this mock.
I think the issue is a multithreading one.
When you call initConnection, it calls mConnection.connect() in a Thread
The problem you are having is that this Thread takes some time to complete and you end up calling verify(mockedZConnection, times(1)).connect(); before the Thread actually reached the connect() call.
A way to make sure about it is to join the Thread after you start it, it will wait until the Thread has finished before continuing:
mThread.start();
try {
mThread.join();
} catch (InterruptedException i) {
i.printStackTrace();
}
Now both tests should work.
This of course is not acceptable in the code, because it negated the use of a Thread. You will need an other way to test it.
A way I can think of would be to wait for the Thread to complete in your test before checking the mock:
#Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Wait for the Thread to complete
while(zConnectionService.mThread.isAlive()) {
Thread.sleep(100);
}
verify(mockedZConnection, times(1)).connect();
}
Tried and it works fine for me. Not sure it is a best practice though as you need to make public some internals of your class, which violates encapsulation
maybe having a package protected isThreadAlive() method on your ZConnectionService class could be acceptable
boolean isThreadAlive() {
return mThread.isAlive();
}
and the loop in the test
while(zConnectionService.isThreadAlive()) {
Thread.sleep(100);
}

Android Java - how to refactor out a try-catch-finally with a throw in the finally, all inside an abstract class?

Good afternoon,
I'm currently working with the code from:
https://github.com/kevinsawicki/http-request
I'm attempting to refactor the code as applicable to clear all the Android Studio warnings before I include it in a project I'm working on. Currently I'm working with the following nested abstract class:
///////////////////////////////////////////////////////////////////////////////////////////////
protected static abstract class Operation<V> implements Callable<V> {
protected abstract V run() throws HttpRequestException, IOException;
protected abstract void done() throws IOException;
public V call() throws HttpRequestException {
Log.d(TAG, "in HttpRequest nested class Operation call");
boolean thrown = false;
try {
return run();
} catch (HttpRequestException e) {
thrown = true;
throw e;
} catch (IOException e) {
thrown = true;
throw new HttpRequestException(e);
} finally {
try {
done();
} catch (IOException e) {
if (!thrown) {
throw new HttpRequestException(e);
}
}
}
}
} // end Operation
This is producing the following warning for having a throw inside a finally block:
I've been looking at this for a while but I can't seem to find a way to factor out this warning. I did see this other answer:
throws Exception in finally blocks
However I would really prefer to not introduce another function. If I was to introduce a closeQuietly function, would that go inside or outside the nested class listed above? Please advise, thanks!
It's just a warning. If you read the explanation it says (emphasis mine)
While occasionally intended, such throw statements may mask exceptions thrown and tremendously complicate debugging.
If you need to do it, then do it, but just make sure it's actually what you want to do and understand the implications (it's akin to saying "do you really want to do this?!"). Not all of IntelliJ's warnings can be eliminated.
Edit based on follow up: You have to ask yourself if your framework needs to throw that exception in the finally block. You can implement a similar approach to what was linked without using another function (just replace the throw statement in finally with a log statement), but that might not be desirable. It depends entirely on the potential error conditions.
If, for example, you're expecting done() to run into issues whenever you've previously received an IOException or an HttpRequestException then you probably don't need to throw anything in the finally block (just log it). But, if you need to make sure you alert the user if something went wrong trying to clean up, then you do need to throw there and you should ignore the warning.
I suppose you could do something like this:
protected static abstract class Operation<V> implements Callable<V> {
protected abstract V run() throws HttpRequestException, IOException;
protected abstract void done() throws IOException;
public V call() throws HttpRequestException {
Log.d(TAG, "in HttpRequest nested class Operation call");
boolean thrown = false;
try {
return run();
} catch (IOException e) {
throw new HttpRequestException(e);
} finally {
try {
done();
} catch (IOException e) {
// handle the IOException
}
}
}
} // end Operation
If an HttpRequestException is ever thrown it'll be thrown by the method, you still transform the IOException into an HttpRequestException (not quite sure why you want to do that), and in the finally block you would need to catch and handle the IOException appropriately.

A method from a library is swallowing an exception that I would like to catch

I am using the class FutureTask that takes a Callable object in his constructor and calls call() from inside his run method like this:
public void run() { //Thread
while(true) {
try {
FutureTask<String> task = taskQueue.take();
task.run(); //executing call() somehow
}
catch (InterruptedException e) {
System.out.println("Thread finishing from interrupt()...");
break; //I would like to break the loop if I receive the exception
}
}
}
My call implementation is like this:
#Override
public String call() throws InterruptedException {
Thread.sleep(taskTime);
//After calling interrupt() on this thread an InterruptedException is thrown
return "someString"; // this is not reached
}
But I think that the run method is swallowing the exception since I can not reach the catch block. Do you have any ideas?
I call thread.interrupt(); with thread being the thread running run().
To be cleared: when task.run() is running, it is executing Thread.sleep(taskTime); which correctly throws the exception, but the run() method seems to swallow it.
The problem is this: I have a library class (that I can not modify) which takes an object to run a particular method which could throw an exception. This library class acts like a wrapper and it seems like it swallows the exception instead of propagating it. What would you do?

How to throw a checked exception from a java thread?

Hey, I'm writing a network application, in which I read packets of some custom binary format. And I'm starting a background thread to wait for incoming data. The problem is, that the compiler doesn't let me to put any code throwing (checked) exceptions into run(). It says:
run() in (...).Listener cannot implement run() in java.lang.Runnable; overridden method does not throw java.io.IOException
I want the exception to kill the thread, and let it be caught somewhere in the parent thread. Is this possible to achieve or do I have to handle every exception inside the thread?
To be able to send the exception to the parent thread, you can put your background thread in a Callable (it allows throwing also checked exceptions) which you then pass to the submit method of some Executor. The submit method will return a Future which you can then use to get the exception (its get method will throw an ExecutionException which contains the original exception).
Caveat: this may not meet your needs if you have to use the exception mechanism.
If I understand you correctly, you don't actually need the exception to be checked (you've accepted the answer suggesting an unchecked exception) so would a simple listener pattern be more appropriate?
The listener could live in the parent thread, and when you've caught the checked exception in the child thread, you could simply notify the listener.
This means that you have a way of exposing that this will happen (through public methods), and will be able to pass more information than an exception will allow. But it does mean there will be a coupling (albeit a loose one) between the parent and the child thread. It would depend in your specific situation whether this would have a benefit over wrapping the checked exception with an unchecked one.
Here's a simple example (some code borrowed from another answer):
public class ThingRunnable implements Runnable {
private SomeListenerType listener;
// assign listener somewhere
public void run() {
try {
while(iHaveMorePackets()) {
doStuffWithPacket();
}
} catch(Exception e) {
listener.notifyThatDarnedExceptionHappened(...);
}
}
}
The coupling comes from an object in the parent thread having to be of type SomeListenerType.
This answer is based on Esko Luontola one but it provides a working example.
Unlike the run() method of the Runnable interface the call() method of Callable allows to throw some exceptions. Here is an implementation example :
public class MyTask implements Callable<Integer> {
private int numerator;
private int denominator;
public MyTask(int n, int d) {
this.numerator = n;
this.denominator = d;
}
#Override
// The call method may throw an exception
public Integer call() throws Exception {
Thread.sleep(1000);
if (denominator == 0) {
throw new Exception("cannot devide by zero");
} else {
return numerator / denominator;
}
}
}
Executor provides a mechanism to run a Callable inside a thread and to handle any kind of exceptions :
public class Main {
public static void main(String[] args) {
// Build a task and an executor
MyTask task = new MyTask(2, 0);
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
try {
// Start task on another thread
Future<Integer> futureResult = threadExecutor.submit(task);
// While task is running you can do asynchronous operations
System.out.println("Something that doesn't need the tasks result");
// Now wait until the result is available
int result = futureResult.get();
System.out.println("The result is " + result);
} catch (ExecutionException e) {
// Handle the exception thrown by the child thread
if (e.getMessage().contains("cannot devide by zero"))
System.out.println("error in child thread caused by zero division");
} catch (InterruptedException e) {
// This exception is thrown if the child thread is interrupted.
e.printStackTrace();
}
}
}
What I do is to catch the exception in the thread and store it as a member variable of the Runnable. This exception is then exposed via a getter on the Runnable. I then scan all the threads from the parent to see if any had exceptions, and take the appropriate action.
If you really cannot do anything useful when the exception is raised you can wrap the checked exception in a RuntimeException.
try {
// stuff
} catch (CheckedException yourCheckedException) {
throw new RuntimeException("Something to explain what is happening", yourCheckedException);
}
the thread can't throw the exception to any other thread (nor to the main thread). and you cannot make the inherited run() method throw any checked exceptions since you can only throw less than the inherited code, not more.
If your thread's code throw a RuntimeExpection, you doesn't need to add run() throw Exception.
But use this solution only when appropriate because this can be a bad pratice:
http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
Any RuntimeException or unchecked Exception can help you. Maybe you'll need to create your own RuntimeException
On the assumption that your code is in some kind of loop, you'd write:
public class ThingRunnable implements Runnable {
public void run() {
try {
while(iHaveMorePackets()) {
doStuffWithPacket()
}
} catch(Exception e) {
System.out.println("Runnable terminating with exception" + e );
}
}
}
The exception will automatically break you out of your loop, and at the end of the run() method, the thread will stop.
Use this Runnable to create your Thread:
public abstract class TryRunner implements Runnable{
protected abstract void tryToRun();
protected void onException(Exception e){}
#Override
final public void run() {
try{ tryToRun(); }catch(Exception e){ e.printStackTrace(); onException(e); }
}
}
Wrapping your exception inside a RuntimeException seems to do the trick.
someMethod() throws IOException
{
try
{
new Thread(() ->
{
try
{
throw new IOException("a checked exception thrown from within a running thread");
}
catch(IOException ex)
{
throw new RuntimeException("a wrapper exception", ex); // wrap the checked exception inside an unchecked exception and throw it
}
}).start();
}
catch(RuntimeException ex) // catch the wrapped exception sent from within the thread
{
if(ex.getCause() instanceof IOException)
throw ex.getCause; // unwrap the checked exception using getCause method and use it however you need
else
throw ex;
}
}

Categories