运行 不同的线程不允许显示 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);实际上是调用网络服务器发送一些数据。

问题是 ResultActivitycall 调用 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.

所以你的 ActivityonCreate 方法调用了那个东西,然后阻塞直到 call(在另一个线程上 运行ning)returns 其结果。所以onCreate没有完成,布局也没有完成。

如果你想使用那个阻塞代码,但在视图布局之后,我会使用 Activity lifecycle 的另一部分,比如 onStart(设置一个标志,这样你只 运行 它一次!)。否则,您将需要使用其他一些并发技术来获取结果并使用它。这取决于您对 call 函数

的结果实际执行的操作

Feature.get() 是阻塞调用。 UI 线程在等待对 return 的调用时被阻塞,因此无法负责绘制布局。尝试将结果侦听器传递给 ResultListenerServerConnection 并使用这两个回调相应地更新您的 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 字母(驼峰式)开头。