如果任务在Activity处于后台时完成,则处理AsyncTask

时间:2015-08-12 18:18:37

标签: android android-asynctask

我已经使用AsyncTasks了一段时间,但是我最近遇到了一个我不确定如何正确处理的情况。由于我认为这是一种常见的情况,所以我决定在这里提出这个问题。

因此,我尝试使用AsyncTask进行简单调用,以便将用户签名到应用程序中。调用完成后,如果成功,则应该将用户带到另一个活动。这个逻辑很简单。当用户在登录呼叫返回之前导航离开应用程序时,问题就出现了。在这种情况下,我应该在onPostExecute()中做什么?

我看到一些应用程序所做的是,无论如何,只要活动仍在,并且将启动下一个活动,他们仍会继续通话。然而,这会产生一种奇怪的体验,用户可以远离应用程序导航,几秒钟后,应用程序就会弹回到他们的脸上。当然,我想避免这样做。

更新 示例代码:

public class ExampleActivity extends Activity {
    private boolean mIsPaused;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        Button btnSignIn = (Button) findViewById(R.id.btn_sign_in);
        btnSignIn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new SignInTask(ExampleActivity.this).execute();
            }
        });
        ...
    }

    @Override
    protected void onPause() {
        super.onPause();
        mIsPaused = true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        mIsPaused = false;
    }

    private boolean isPaused() {
        return mIsPaused;
    }

    ...
    private static class SignInTask extends AsyncTask<Void, Void, SomeResult> {

        private final WeakReference<ExampleActivity> mAct;

        public SignInTask(ExampleActivity act) {
            mAct = new WeakReference<ExampleActivity>(act);
        }

        @Override
        protected SomeResult doInBackground(Void... params) {
            return mApi.signIn(creds);
        }

        @Override
        protected void onPostExecute(SomeResult result) {
            if (result.getCode() == OK) {
                ExampleActivity act = mAct.get();
                if (act != null) {
                    if (act.isPaused()) {
                        // do something
                    } else {
                        startActivity(new Intent(act, NextActivity.class));
                    }
                } else {
                    // do something
                }
            }

        }
    }
}

5 个答案:

答案 0 :(得分:1)

使您的AsyncTask类成为静态内部类。

答案 1 :(得分:1)

非常有趣的问题...通过使用布尔值来启动您所启动的内容,您可以在活动暂停时将活动收到的响应保存到SharedPreferences,如果不是,则可以继续正常处理。如果活动稍后恢复(或重新创建),请检查是否存在已保存的响应并进行相应处理。我正在思考以下几点:

import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;

public class TaskActivity extends Activity {

    private static final String KEY_RESPONSE_JSON = "returned_response";

    private boolean paused = false;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        // don't setup here, wait for onPostResume() to figure out what to do
    }

    @Override
    public void onPostResume(){
        super.onPostResume();
        paused = false;

        if(isSavedResponseAvailable()) processResponse(getSavedResponse());
        else setup();
    }

    @Override
    public void onPause(){
        paused = true;
        super.onPause();
    }

    private void setup(){ 
        // normal setup
    }

    public void onReceiveResponse(JSONObject response){
        if(paused) setSavedResponse(response);
        else processResponse(response); 
    }

    private void processResponse(JSONObject response){
        // Continue with processing as if they never left

        getSharedPreferences(this.getClass().getName(), 0).edit().clear().commit(); // Clear everything so re-entering won't parse old data
    }   

    private boolean isSavedResponseAvailable(){
        return getSavedResponse() != null;
    }

    private JSONObject getSavedResponse(){
        try{
            return new JSONObject(getSharedPreferences(this.getClass().getName(), 0).getString(KEY_RESPONSE_JSON, ""));
        }
        catch(Exception e){ }
        return null;
    }

    private void setSavedResponse(JSONObject response){
        getSharedPreferences(this.getClass().getName(), 0).edit().putString(KEY_RESPONSE_JSON, response.toString()).commit();
    }
}

显然,假设您对该任务的响应是JSON,但是没有理由不能将其扩展为单独保存数据并从保存的首选项数据重建必要的响应对象。

就干净的方法而言,虽然......我给出了大约3/10,但我想不出更好的东西(好吧,除了使TaskActivity抽象并强制实现覆盖{{1}但是,对于像4/10这样的情况来说,这只会稍微好一些。

答案 2 :(得分:0)

我建议在post执行中添加一个try / catch语句 - 据我所知,在这种情况下会发生什么样的事情会导致某种Window Manager异常。

然而,我强烈建议使用onPause方法停止任何异步任务(使用cancel方法),这意味着您不会中断它们。

http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean)

  

public final boolean cancel(boolean mayInterruptIfRunning)

     

在API级别3中添加   尝试取消执行此任务。如果任务已经完成,已经取消或由于某些其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则此任务永远不会运行。如果任务已经启动,则mayInterruptIfRunning参数确定执行此任务的线程是否应该在尝试停止任务时被中断。

     

调用此方法将导致在doInBackground(Object [])返回后在UI线程上调用onCancelled(Object)。调用此方法可确保永远不会调用onPostExecute(Object)。调用此方法后,应定期从doInBackground(Object [])检查isCancelled()返回的值,以尽早完成任务。

     

参数   mayInterruptIfRunning
如果执行此任务的线程应该被中断,则为true;否则,允许完成正在进行的任务。   返回   如果任务无法取消,则为false,通常是因为它已经正常完成;否则为真   也可以看看   取消()   onCancelled(对象)

答案 3 :(得分:0)

boolean isRunning; //set it to true in onResume, and false in onStop
boolean isWaiting; // set it to true in onPostExecute, if "isRunning" is false

签入onResume isWaiting是否为真,如果是,请将用户带到另一个屏幕。

答案 4 :(得分:0)

sed 's/^$/Hello/' file1