-1

I have been reading a good amount about AsyncTasks but I can't figure something out. I have an AsyncTask that I start that is used for an HttpURLConnection for a request from my database. The database work is done in doInBackground() and I have a ProgressDialog that runs on the UI thread that just shows that it is loading. Once the doInBackground() is complete though, my code continues even though I have some things in the onPostExecute() that need to happen before the code can continue.

Is there a way to keep the AsyncTask asynchronous so I can run the ProgressDialog and do the database work in doInBackgroun() at the same time and also have it wait to continue until onPostExecute() has been called?

To clarify:

I cannot just call a function in the onPostExecute() call. At launch an AlertDialog is opened in order for the user to input their username and password so they can login. When they hit login, the AsyncTask is run. I need the AlertDialog to know when the onPostExecute() is complete as well in order to close it. Otherwise I'll be stuck with it.

Here is the code for the AlertDialog in the beginning:

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();

Here is my code for the login:

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();
        }
    }
}
sabo
  • 911
  • 13
  • 37
  • Your description is a little unclear. Just don't execute whatever code that needs to wait until you've done what you need to do in `onPostExecute()`. – Mike M. Jul 10 '16 at 02:54
  • In `onPostExecute()`, dismiss the `ProgressDialog`, and if the login is successful, dismiss the `AlertDialog`. I'm not really seeing where the problem is. – Mike M. Jul 10 '16 at 03:38
  • @MikeM. I guess I am just not seeing how I will be able to dismiss the AlertDialog with the way I have things laid out. – sabo Jul 10 '16 at 03:53
  • Create an `interface` that you can use to call back to where your `AlertDialog` is, and dismiss it there. There are examples in [this post](http://stackoverflow.com/questions/12575068/how-to-get-the-result-of-onpostexecute-to-main-activity-because-asynctask-is-a). – Mike M. Jul 10 '16 at 04:11
  • 1
    @MikeM. That worked great. Didn't even think of using an interface there. – sabo Jul 10 '16 at 16:27
  • @MikeM. If you put that in an answer I will go ahead and accept it so you get credit. – sabo Jul 10 '16 at 22:55
  • It's cool. I didn't really do anything. Just showed ya where to find the answer. You can post an answer with details of your actual implementation, if ya want. Thanks, though. Appreciate it. Cheers! – Mike M. Jul 11 '16 at 02:29

4 Answers4

0

you can do this in following way:

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.
    }
}

}

  • use alert.create().cancel() on post method to dismiss the alert dialog. – Android android Jul 10 '16 at 04:08
  • the login AlertDialog and the AsyncTask are in different classes. I went ahead and passed the AlertDialog.Builder instance to the Database class in order to call alert.create().cancel() in the onPostExecute() function but the AlertiDialog was not affected. – sabo Jul 10 '16 at 04:18
  • make asyncLogin class as an inner class of the class in which you are having your alert dialog and then try it. – Android android Jul 10 '16 at 04:30
0

i think what you want is not very difficult, you can use following code :

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.
    }
}
}
Amin Rahkan
  • 119
  • 3
  • 11
  • loading.dismiss(); is not correct , you should dismiss your dialog in ui thread. runOnUiThread(new Runnable() { public void run() { loading.dismiss(); } }); – Amin Rahkan Jul 10 '16 at 07:04
  • loading.dismiss(); is called in the onPostExecute() function for the AsyncTake. That function runs on the UI thread. – sabo Jul 10 '16 at 15:19
0

If I understand it correctly, you have two dialogs(progress and alert) and you want to dismiss one of them after you get login response and keep the other one till database work is done.

If yes, I think you would need two async tasks, one for login and one for database work. Dismiss one of the dialogs in the postExecute(0 of first async task and Call the database async task from the postExecute of the first async task and then dismiss the second on the completion of the second async task.

Hitesh
  • 331
  • 2
  • 10
0

This post gives an example of using an interface in order to have a function called when the onPostExecute() is called so that it was possible to access the AlertDialog from where I needed to access it.

Community
  • 1
  • 1
sabo
  • 911
  • 13
  • 37