0

我有这个活动:

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

这段代码缺少什么?

4

3 回答 3

1

Feature.get()是阻塞调用。UI 线程在等待该调用返回时被阻塞,因此无法处理您的布局。尝试将结果侦听器传递ResultListenerServerConnection并使用这两个回调相应地更新您的 UI

于 2020-08-25T19:57:41.063 回答
1

DecodeAndSend从主线程调用。它调用Future.get()which 等待作业完成,因此它阻塞了主线程。您也应该从后台线程调用此方法。我认为可以将它发送到同一个线程池,因为它是在它等待的第一个作业之后提交的。

您无法从该方法返回任何有关请求结果的信息,因为它是异步的。

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 中的约定是始终以小写字母(驼峰式)开头方法名称。

于 2020-08-25T19:57:59.120 回答
0

Future.get()是一个阻塞调用- 执行停止,直到结果到达

结果只能在计算完成时使用方法 get 检索,必要时阻塞,直到它准备好。

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

如果您想使用该阻塞代码,但在视图布局之后,我会使用Activity 生命周期的另一部分,例如onStart(设置一个标志,以便您只运行一次!)。否则,您将需要使用其他一些并发技术来获取结果并使用它。这取决于您对call函数结果的实际操作

于 2020-08-25T19:57:26.607 回答