如何防止在Activity关闭时添加Fragment

时间:2014-05-24 21:05:45

标签: java android android-fragments android-service android-handler

我正在创建一个Activity,与Service进行通信,通过POST方法从互联网上下载一些数据。为此,我使用Messenger。这是我的代码,让你更清楚:

我的onCreated()方法:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_comments);

    CommentsHandler commentsHandler = new CommentsHandler(this, savedInstanceState);
    Messenger messenger = new Messenger(commentsHandler);

    Intent serviceIntent = new Intent(this, WindowService.class);
    serviceIntent.putExtra("messenger", messenger);
    serviceIntent.putExtra("state", 888);
    serviceIntent.putExtra("number", getIntent().getStringExtra("number"));
    startService(serviceIntent);
}

我的Service主题中的代码,通过Activity对象将结果数据发布到Messenger

    /** ... **/
    Messenger messenger = intent.getParcelableExtra("messenger");
    /** ... **/
    Message resultMsg = this.obtainMessage();
    resultMsg.obj = jParser.getArrayList(); //This is an ArrayList of my downloaded data.
    messenger.send(resultMsg);

Activity中用于处理Message中的Service的代码:

public static class CommentsHandler extends Handler {
    Bundle mSavedInstanceState;
    ActionBarActivity activity;

    public CommentsHandler(Activity a, Bundle savedInstanceState) {
        activity = (ActionBarActivity) a;
        mSavedInstanceState = savedInstanceState;
    }

    @Override
    public void handleMessage(Message msg) {
        comments = (ArrayList<HashMap<String, String>>) msg.obj;
        if (mSavedInstanceState == null && msg.arg1 != 793) {
            activity.getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new CommentsFragment()).commit();
        } else if (msg.arg1 == 793) { //793 is my preferred code to determine
                                      //if the internet connection could not be
                                      //established when the Service was trying
                                      //to download the data.
            activity.finish();
        }
    }
}

问题是:如果我打开Activity并在下载数据之前将其关闭,则此代码.add(R.id.container, new CommentsFragment()).commit();会向我显示错误Can not perform this action after onSaveInstanceState,因为此代码仅在我的Service中的数据经过Messenger对象处理和发送,但当时Activity已被用户关闭,因此无法添加Fragment。如何解决这个问题?如何在添加Activity之前检查Fragment是否未关闭/关闭?或者,更好的是,如何在Activity的{​​{1}}方法中停止运行该代码的线程,以便在onDestroy()关闭时不会执行它?提前谢谢!

3 个答案:

答案 0 :(得分:3)

在您的活动中,您应该创建一个布尔值来检查活动是否可见:

public ActionBarActivity extends Activity {
  private boolean isActivityVisible = false;

  @Override
  protected void onResume(){
     isActivityVisible = true;
  }

  @Override
  protected void onPause(){
     isActivityVisible = false;
  }

  public boolean isVisible(){
     return this.isActivityVisible;
  }
}

然后修改Handler类定义:

public static class CommentsHandler extends Handler {
Bundle mSavedInstanceState;
ActionBarActivity activity;

public CommentsHandler(Activity a, Bundle savedInstanceState) {
    activity = (ActionBarActivity) a;
    mSavedInstanceState = savedInstanceState;
}

@Override
public void handleMessage(Message msg) {
    // here you check if your activity is no longer visible and then break up
    if(activity == null || !activity.isVisible())
        return;

    comments = (ArrayList<HashMap<String, String>>) msg.obj;
    if (mSavedInstanceState == null && msg.arg1 != 793) {
        activity.getSupportFragmentManager().beginTransaction()
            .add(R.id.container, new CommentsFragment()).commit();
    } else if (msg.arg1 == 793) { //793 is my preferred code to determine
                                  //if the internet connection could not be
                                  //established when the Service was trying
                                  //to download the data.
        activity.finish();
    }
}
}

答案 1 :(得分:1)

最小的变化是在Activity中有一个布尔字段,在onResume()中将其设置为true,在onPause()中设置为false,并在handleMessage()中检查其值(即忽略)如果标志当前为false则消息。)

使用handleMessage()执行此操作,而不是使用Messenger和BroadcastReceiver。在onResume()中注册接收方,并在onPause()中取消注册。这样,服务的广播将被忽略。

无论如何,这两种解决方案基本相同,但广播有点&#34;更高级别&#34;。

如果活动暂停,则假定您对服务的结果不感兴趣。如果您(例如,如果您退出应用程序并重新登录,并且需要显示更新),那么您应该将接收的数据放在一个字段中并在以下onResume()处理它。

答案 2 :(得分:1)

你这样做的方式与我处理它的方式不同,但是使用你拥有的东西我会做出这些调整:

public static class CommentsHandler extends Handler {
    Bundle mSavedInstanceState;
    ActionBarActivity activity;

    public CommentsHandler(Activity a, Bundle savedInstanceState) {
        activity = (ActionBarActivity) a;
        mSavedInstanceState = savedInstanceState;
    }

    public void setActivity(Activity a){
        activity = a;
    }

    @Override
    public void handleMessage(Message msg) {
        if(activity == null){
            return;
        }
        comments = (ArrayList<HashMap<String, String>>) msg.obj;
        if (mSavedInstanceState == null && msg.arg1 != 793) {
            activity.getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new CommentsFragment()).commit();
        } else if (msg.arg1 == 793) { //793 is my preferred code to determine
                                      //if the internet connection could not be
                                      //established when the Service was trying
                                      //to download the data.
            activity.finish();
        }
    }
}

然后我会使用你的活动onPause()/ onResume()方法来表示:

@Override
protected void onPause() {
    super.onPause();
    commentsHandler.setActivity(null);  
}

@Override
protected void onResume() {
    super.onResume();
    commentsHandler.setActivity(this);  
}