I have this piece of an activity:
public class ResultActivity extends AppCompatActivity implements ResultListener {
private String code = "";
private String data = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
code = intent.getStringExtra("code");
data = intent.getStringExtra("data");
MyExternal.DecodeAndSend(this, code, data);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Where MyExternal
is a class in other library.
The method DecodeAndSend
is something like this:
public static boolean DecodeAndSend(ResultListener caller, String codigo, String data)
{
try {
ExecutorService pool = Executors.newFixedThreadPool(1);
HashMap<String,String> arguments = new HashMap<>();
Future<String> resultado = pool.submit(new ServerConnection(caller, url, arguments));
String status = resultado.get();
if (status.equals("OK"))
caller.OnSuccess();
else
caller.OnError(status);
pool.shutdown();
return true;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return false;
}
Finally, ServerConnection
class implements Callable<String>
so I show you the call
method:
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "OK";
}
The call to Thread.sleep(2000);
is actually a call to a web server to send some data.
The problem is that the ResultActivity
does not show its layout until the call
call returns.
What is missing in this code?
DecodeAndSend
is called from the main thread. It calls Future.get()
which waits for the job to finish, so it's blocking the main thread. You should call this method from a background thread as well. I think it would be okay to send it to your same thread pool since it is submitted after the first job that it will wait for.
You cannot return anything about the request results from this method, because it is asynchronous.
public static void DecodeAndSend(ResultListener caller, String codigo, String data)
{
ExecutorService pool = Executors.newFixedThreadPool(1);
HashMap<String,String> arguments = new HashMap<>();
Future<String> resultado = pool.submit(new ServerConnection(caller, url, arguments));
pool.submit(new Runnable() {
public void run () {
try {
String status = resultado.get();
if (status.equals("OK"))
caller.OnSuccess();
else
caller.OnError(status);
pool.shutdown();
return;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
caller.OnError(null); // No status, only an exception
});
}
However, your ServerConnection
class already takes a caller
parameter, so it should probably just handle the callback itself. And depending on what you're doing in the callback, you might want to post the callback calls to the main thread.
By the way, convention in Java is to always start method names with a lower-case letter (camel case).