在不阻塞线程的情况下获取AsyncTask的结果

时间:2018-07-12 08:03:09

标签: java android multithreading user-interface android-asynctask

我有在AsyncTask中将请求发送到REST API的代码。 另外,我在preExecute()中有一个ProgressDialog初始化,在postExecute()中有它的解除。

我希望ProgressDialog显示一个不确定的微调器(您知道,正在加载动画),但是我也需要得到一个结果。 get()阻塞了我在其中调用主线程的情况-这种情况的解决方法是什么?

主线程(主要活动)

LoginTask task_login = new LoginTask();
                AsyncTask<String, Void, JSONObject> response = task_login.execute(et_username.getText().toString(), et_password.getText().toString());
                try {
                    JSONObject json = response.get();
                    Toast.makeText(MainActivity.this, json.toString(), Toast.LENGTH_SHORT).show();
                } catch (InterruptedException e) {
                    Toast.makeText(MainActivity.this, "Interrupted.", Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    e.printStackTrace();
                }

AsyncTask(虚拟doInBackground):

public class LoginTask extends AsyncTask<String, Void, JSONObject> {
    private LoginTask self = this;
    private ProgressDialog progressDialog;

    @Override
    protected JSONObject doInBackground(String... params) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progressDialog = ProgressDialog.show(MainActivity.context,
                "Logging in...", "");
        progressDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
                MainActivity.context.getResources().getResourceEntryName(R.string.dialog_button_cancel), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

        progressDialog.setCanceledOnTouchOutside(false);
        progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                self.cancel(true);
            }
        });
    }

    @Override
    protected void onPostExecute(JSONObject jsonObject) {
        super.onPostExecute(jsonObject);

        progressDialog.dismiss();
    }

}

3 个答案:

答案 0 :(得分:1)

您可以使用AsyncTask的onProgressUpdate()方法在UI线程上执行操作(例如显示或更新加载动画),而doInBackGround()在另一线程上执行后台工作。

基本上,您从doInBackGround()中调用publishProgress()方法,该方法又调用onProgressUpdate()。

查看AsyncTask上的Android reference page为例。

答案 1 :(得分:0)

1-您可以使用回调方法。 但是请记住,您应该在主线程中调用它。

2-您可以使用LocalBroadcastManager来通过Intent发送结果。

3-我认为您可能想在更可靠的应用程序消息传递库中使用。我经常使用的一个示例是EventBus

答案 2 :(得分:0)

请查看AsyncTask https://developer.android.com/reference/android/os/AsyncTask#usage

的用法

有一个回调函数onPostExecute,该函数返回(作为参数)您请求的值:

private class RestTask extends AsyncTask<Object, Object, String> {
    protected String doInBackground(Object... args) {
        // this happend on background thread
        return downloadData();
    }

    protected void onPreExecute() {
        // this happend on UI thread
        showSpinner();
    }

    protected void onPostExecute(String result) {
        // this happend on UI thread
        hideSpinner();
        doSomethingWithDownloadResult(result);
    }
}

用法:

new RestTask().execute()

在您编辑问题时,这是

try {
    JSONObject json = response.get();
    Toast.makeText(MainActivity.this, json.toString(), Toast.LENGTH_SHORT).show();
} catch (InterruptedException e) {
    Toast.makeText(MainActivity.this, "Interrupted.", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
    e.printStackTrace();
}

应该在以前的Tasks onPostExecute方法中调用,这样,您将不会使用get方法阻止UI等待登录结果。