Cornholio
Cornholio

Reputation: 985

How can I run an AsyncTask with a dialog after finishing activity?

I have two activities, one for displaying entries and another for creating them. Here's a standard use case:

What I want to add is an AsyncTask that runs after the viewing activity is completely loaded. This AsyncTask shows a dialog while it's running. The problem is, when I put this code into onActivityResult() like this:

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) {     
    super.onActivityResult(requestCode, resultCode, data); 
        switch(resultCode) { 
        case (Activity.RESULT_OK): {
            mEntryListFragment.updateContent();
            runAsyncTaskHere();
        }
    }
}

It runs the AsyncTask before it goes back to the main activity, and no dialog shows. Any ideas what I can do?

Edit: here's the AsyncTask.

public static class LogInTask extends AsyncTask<String, Void, Integer> {
    protected String username = "";
    protected String password = "";
    protected ProgressDialog dialog;
    protected boolean showDialogs;

    public LogInTask(boolean sd) {
        this.showDialogs = sd;
    }

    @Override
    protected void onPreExecute() {
        if (this.showDialogs) dialog = ProgressDialog.show(MainActivity.getContext(), null, "Logging in...");
    }

    @Override
    protected Integer doInBackground(String... login) {
        if (Config.DEBUG) Log.d(Config.APP_NAME, "in doInBackground() of LogInTask");
        HttpResponse response = null;
        String username = login[0];
        String password = login[1];
        try {
            HttpPost httpPost = new HttpPost(URL_BASE + URL_LOGIN);

            // main (JSON) login method
            JSONObject json = new JSONObject().put("user", 
                    new JSONObject()
                        .put("email", username)
                        .put("password", password)
                        .put("remember_me", Config.REMEMBER_LOGIN)
                    );
            this.username = username;
            this.password = password;
            StringEntity se = new StringEntity(json.toString());
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            httpPost.setEntity(se);

            response = httpclient.execute(httpPost);
            String responseEntity = EntityUtils.toString(response.getEntity());
            JSONObject result = new JSONObject(responseEntity);
            return result.getBoolean("success") ? 1 : KEY_ERROR; // Return 1 if successful and -1 if not
        } catch (UnknownHostException e) {
            e.printStackTrace();
            KEY_ERROR;
        } catch (Exception e) {
            e.printStackTrace();
            return KEY_ERROR;
        }
    }

    @Override
    protected void onPostExecute(Integer result) {
        if (this.showDialogs) {
            dialog.dismiss();
            String text = result == 1 ? "Login was successful." : "Login failed!";
            makeToast(text);
        }
    }
}

Edit 2: I tried this:

boolean needToUpdate = false;
@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) {     
    super.onActivityResult(requestCode, resultCode, data); 
    switch(resultCode) { 
        case (Activity.RESULT_OK): {
            mEntryListFragment.updateContent();
            needToUpdate = true;
        }
    }
}

@Override
public void onResume() {
    super.onResume();
    if (needToUpdate) {
        runAsyncTaskHere();
        mEntryListFragment.updateContent();
    }
    needToUpdate = false;
}

and it did the same thing.

Edit 3: here're the relevant sections of the AndroidManifest:

 <activity 
        android:name=".MainActivity" 
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".AddEntryActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:configChanges="orientation" />

Upvotes: 2

Views: 1674

Answers (5)

lenik
lenik

Reputation: 23528

AsyncTask is a class for background processing, please, don't try to use it to do something with your UI or Activities, it always leads to a bad and unpredictable behaviour.

Maybe I should elaborate a little. Activities come and go, get killed and restored, destroyed and recreated as a usual way of theirs lives. It's absolutely normal.

Your AsyncTask may easily outlive your Activity, so when you're trying to access UI, it's already gone. Destroyed and recreated again, and all you've got is a dead pointer, which gives you an exception. Load your files in AsyncTask, do networking, access database. Just don't try to access UI/Activities, or your application will eventually crash and burn.

Upvotes: 2

Joel Bodega
Joel Bodega

Reputation: 644

Just a thought.

  1. Are you sure you are retrieving the proper context.
  2. Is the boolean set correctly?

Plus, I do believe you are using HttpCore. From what I remember it requires some more attention networking and dis/connection wise due to it's granularity (compared to the HttpConnection class available by default). As such I don't think it is the best to use it with AsyncTask classes since they have little connection with the UI thread. Thus don't give much control for the user and may live beyond application's lifespan.

Upvotes: 0

SKK
SKK

Reputation: 5271

  1. When you click on the Button to create new Entry, launch New Activity. but keep the Activity with entries. do not call finish() after intent.
  2. After creation, and on clicking DONE, just close the Current Activity.(call finish())
  3. mEntryListFragment.updateContent write this method in onStart() of the activity displaying entries.

Upvotes: 1

Tushar
Tushar

Reputation: 261

i think , you have to use Concept of callbacks ,

like when ever , loading is complete , implement your callback inside which you can deal with AsyncTask and after performing your task inside doInBackGround() , you can use onPostExecute() .

try something like this ,

Callback_interface
{
    void async_run_after_some_time() ;
}

main_activity_class extends Activity Implements Callback_interface
{
    void async_run_after_some_time()
    {
        // implement your toast here 
    }
}

onPostExecute()
{
    main_activity_class ob = new main_activity_class ();
    ob.async_run_after_some_time();
}

Upvotes: 0

Teodor
Teodor

Reputation: 300

Use ProgressDialog to achieve this.Start the dialog onPreExecute() and finish it onPostExecute() methods.You have to override those methods in your async task.

Upvotes: 0

Related Questions