运行 不同的线程不允许显示 activity
Running a different thread does not allow the activity to be displayed
我有这个 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();
}
}
}
其中 MyExternal
是其他库中的 class。
方法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
class 实现了 Callable<String>
所以我向您展示 call
方法:
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "OK";
}
调用Thread.sleep(2000);
实际上是调用网络服务器发送一些数据。
问题是 ResultActivity
在 call
调用 returns 之前不会显示其布局。
此代码中缺少什么?
Future.get()
是一个 blocking call - 执行停止直到结果到达
The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready.
所以你的 Activity
的 onCreate
方法调用了那个东西,然后阻塞直到 call
(在另一个线程上 运行ning)returns 其结果。所以onCreate
没有完成,布局也没有完成。
如果你想使用那个阻塞代码,但在视图布局之后,我会使用 Activity lifecycle 的另一部分,比如 onStart
(设置一个标志,这样你只 运行 它一次!)。否则,您将需要使用其他一些并发技术来获取结果并使用它。这取决于您对 call
函数
的结果实际执行的操作
Feature.get()
是阻塞调用。 UI 线程在等待对 return 的调用时被阻塞,因此无法负责绘制布局。尝试将结果侦听器传递给 ResultListener
到 ServerConnection
并使用这两个回调相应地更新您的 UI
DecodeAndSend
从主线程调用。它调用 Future.get()
等待作业完成,因此它阻塞了主线程。您也应该从后台线程调用此方法。我认为可以将它发送到您的同一个线程池,因为它是在等待的第一个作业之后提交的。
您不能return任何有关此方法的请求结果的信息,因为它是异步的。
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
class 已经采用了 caller
参数,因此它可能应该只处理回调本身。根据您在回调中所做的事情,您可能希望 post 对主线程的回调调用。
顺便说一句,Java 中的约定是方法名称始终以 lower-case 字母(驼峰式)开头。
我有这个 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();
}
}
}
其中 MyExternal
是其他库中的 class。
方法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
class 实现了 Callable<String>
所以我向您展示 call
方法:
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "OK";
}
调用Thread.sleep(2000);
实际上是调用网络服务器发送一些数据。
问题是 ResultActivity
在 call
调用 returns 之前不会显示其布局。
此代码中缺少什么?
Future.get()
是一个 blocking call - 执行停止直到结果到达
The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready.
所以你的 Activity
的 onCreate
方法调用了那个东西,然后阻塞直到 call
(在另一个线程上 运行ning)returns 其结果。所以onCreate
没有完成,布局也没有完成。
如果你想使用那个阻塞代码,但在视图布局之后,我会使用 Activity lifecycle 的另一部分,比如 onStart
(设置一个标志,这样你只 运行 它一次!)。否则,您将需要使用其他一些并发技术来获取结果并使用它。这取决于您对 call
函数
Feature.get()
是阻塞调用。 UI 线程在等待对 return 的调用时被阻塞,因此无法负责绘制布局。尝试将结果侦听器传递给 ResultListener
到 ServerConnection
并使用这两个回调相应地更新您的 UI
DecodeAndSend
从主线程调用。它调用 Future.get()
等待作业完成,因此它阻塞了主线程。您也应该从后台线程调用此方法。我认为可以将它发送到您的同一个线程池,因为它是在等待的第一个作业之后提交的。
您不能return任何有关此方法的请求结果的信息,因为它是异步的。
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
class 已经采用了 caller
参数,因此它可能应该只处理回调本身。根据您在回调中所做的事情,您可能希望 post 对主线程的回调调用。
顺便说一句,Java 中的约定是方法名称始终以 lower-case 字母(驼峰式)开头。