运行其他线程不允许显示活动

问题描述

我有这个活动:

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线程被阻塞,等待该调用返回,因此无法处理绘制布局。尝试将结果侦听器传递到ResultListenerServerConnection并使用两个回调相应地更新您的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函数的结果