等待AsyncTask完成其onPostExecute(),同时保持UI线程为ProgressDialog

时间:2016-07-10 02:38:47

标签: java android android-asynctask

我一直在阅读有关AsyncTasks的大量信息,但我无法解决问题。我有一个AsyncTask我开始用于HttpURLConnection来处理来自我的数据库的请求。数据库工作在doInBackground()中完成,我有一个在UI线程上运行的ProgressDialog,它只显示它正在加载。一旦doInBackground()完成,我的代码就会继续,即使我在onPostExecute()中有一些东西需要在代码可以继续之前发生。

有没有办法让AsyncTask保持异步,所以我可以同时运行ProgressDialog并在doInBackgroun()中运行数据库,并等待它继续,直到调用了onPostExecute()?

澄清:

我不能只在onPostExecute()调用中调用一个函数。在启动时,会打开AlertDialog,以便用户输入用户名和密码,以便他们登录。当他们登录时,运行AsyncTask。我需要AlertDialog知道onPostExecute()何时完成才能关闭它。否则我会被困住。

以下是AlertDialog的代码:

AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setCancelable(false);
final EditText usernameInput = new EditText(context);
usernameInput.setHint("Username");
final EditText passwordInput = new EditText(context);
passwordInput.setHint("Password");
passwordInput.setTransformationMethod(PasswordTransformationMethod.getInstance());
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(usernameInput);
layout.addView(passwordInput);
alert.setView(layout);
alert.setTitle("Login");
alert.setPositiveButton("Login", new DialogInterface.OnClickListener()
{
    @Override
    public void onClick(DialogInterface dialog, int which)
    {
        String username = usernameInput.getText().toString();
        String password = passwordInput.getText().toString();
        if (username != "" && password != "")
        {
            Database database = new Database(currActivity);
            database.Login(username, password);
            if (database.IsLoggedIn())
            {
                SharedPreferences prefs = currActivity.getSharedPreferences("Preferences", currActivity.MODE_PRIVATE);
                prefs.edit().putBoolean("Logged In", true).commit();
                dialog.cancel();
            }
            else ShowLoginAlert(context);
        }
    }
});
alert.show();

以下是我的登录代码:

public void Login(String username, String password)
{
    try
    {
        new AsyncLogin().execute(username, password).get();
    }
    catch (InterruptedException e)
    {
        e.printStackTrace();
    }
    catch (ExecutionException e1)
    {
        e1.printStackTrace();
    }
}

private class AsyncLogin extends AsyncTask<String, String, String>
{
    private static final int READ_TIMEOUT = 1000000;
    private static final int CONNECTION_TIMEOUT = 1000000;
    private URL url = null;
    private HttpURLConnection conn = null;
    ProgressDialog loading = new ProgressDialog(currActivity);

    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        loading.setMessage("\tLoading...");
        loading.setCancelable(false);
        loading.show();
    }

    @Override
    protected String doInBackground(String... params)
    {
        try
        {
            url = new URL("http://mysite/myscript.php");
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
            return "Malformed URL Exception.";
        }

        try
        {
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(READ_TIMEOUT);
            conn.setConnectTimeout(CONNECTION_TIMEOUT);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);

            Uri.Builder builder = new Uri.Builder()
                    .appendQueryParameter("username", params[0])
                    .appendQueryParameter("password", params[1]);

            String query = builder.build().getEncodedQuery();

            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
            writer.write(query);
            writer.flush();
            writer.close();
            conn.connect();
        }
        catch (IOException e1)
        {
            e1.printStackTrace();
            return "Connection Exception.";
        }

        try
        {
            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK)
            {
                InputStream input = conn.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(input));

                StringBuilder result = new StringBuilder();
                String line;

                while ((line = reader.readLine()) != null)
                {
                    result.append(line);
                }

                return result.toString();
            }
            else return "Unsuccessful data retrieval.";
        }
        catch (IOException e2)
        {
            e2.printStackTrace();
            return "Response Exception.";
        }
        finally
        {
            conn.disconnect();
        }
    }

    @Override
    protected void onPostExecute(String result)
    {
        super.onPostExecute(result);

        loading.dismiss();

        if (result.equalsIgnoreCase("true"))
        {
            // Successfully logged in
            SetIsLoggedIn(true);
            Toast.makeText(currActivity, "Successfully logged in.", Toast.LENGTH_LONG).show();
        }
        else
        {
            // Incorrect credentials
            SetIsLoggedIn(false);
            Toast.makeText(currActivity, "Incorrect credentials.", Toast.LENGTH_LONG).show();
        }
    }
}

4 个答案:

答案 0 :(得分:0)

您可以通过以下方式执行此操作:

class main extends Activity {

class Something extends AsyncTask<String, Integer, String> {

    protected void onPreExecute() {
     //  showProgressDialog
    }

    protected String doInBackground(String... params) {
        // Do your heavy stuff...
        return null;
    }

    protected void onPostExecute(String result) {
        // close your progress dialog and than call method which has
        // code you are wishing to execute after AsyncTask.
    }
}

}

答案 1 :(得分:0)

我认为你想要的并不是很困难,你可以使用以下代码:

class main extends MainActivity {

class SampleAsyncTask extends AsyncTask<String, Integer, String> {

    protected void onPreExecute() {
     //  ProgressDialog
    }

    protected String doInBackground(String... params) {
        // Do your database code...
        return null;
    }

    protected void onPostExecute(String result) {
        // close progress dialog 
        // code you are wishing to execute after AsyncTask.
    }
}
}

答案 2 :(得分:0)

如果我理解正确,你有两个对话框(进度和警报),你想在获得登录响应后解除其中一个,并保持另一个直到数据库工作完成。

如果是,我认为你需要两个异步任务,一个用于登录,一个用于数据库工作。关闭postExecute中的一个对话框(第一个异步任务为0,从第一个异步任务的postExecute调用数据库异步任务,然后在第二个异步任务完成时关闭第二个。

答案 3 :(得分:0)

This post给出了一个使用接口的示例,以便在调用onPostExecute()时调用一个函数,以便可以从我需要访问它的位置访问AlertDialog。