问题描述
我有这个活动:
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();
}
}
}
MyExternal
是其他库中的类。
方法DecodeAndSend
是这样的:
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;
}
最后,ServerConnection
类实现了Callable<String>
,所以我向您展示了call
方法:
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "OK";
}
对Thread.sleep(2000);
的调用实际上是对Web服务器发送一些数据的调用。
问题在于,ResultActivity
直到返回call
才显示其布局。
此代码中缺少什么?
解决方法
Feature.get()
是阻止呼叫。 UI线程被阻塞,等待该调用返回,因此无法处理绘制布局。尝试将结果侦听器传递到ResultListener
到ServerConnection
并使用两个回调相应地更新您的UI
DecodeAndSend
。它调用Future.get()
来等待作业完成,因此它阻塞了主线程。您也应该从后台线程调用此方法。我认为可以将它发送到您的同一个线程池中,因为它是在等待的第一个作业之后提交的。
由于此方法是异步的,因此无法返回有关此方法的请求结果的任何信息。
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
});
}
但是,您的ServerConnection
类已经接受了caller
参数,因此它可能应该只处理回调本身。根据您在回调中的操作,您可能希望将回调调用发布到主线程。
顺便说一句,Java中的约定是始终以小写字母(驼峰大写)开头的方法名称。
, Future.get()
是blocking call-执行停止直到结果到达
仅在计算完成后才能使用get方法检索结果,必要时将其阻塞,直到准备就绪为止。
因此,您的Activity
的{{1}}方法将调用该东西,然后阻塞直到onCreate
(在另一个线程上运行)返回其结果。因此call
尚未完成,布局也未完成。
如果您想使用该阻止代码,但在布局视图后,我将使用Activity lifecycle的另一部分,例如onCreate
(设置一个标记,因此您只需运行一次! )。否则,您将需要使用其他并发技术来获取结果并使用它。这取决于您实际使用onStart
函数的结果