【问题标题】:Android setIntent() does not persist new value across recreated activitiesAndroid setIntent() 不会在重新创建的活动中保留新值
【发布时间】:2017-08-27 17:43:52
【问题描述】:

我的一项活动 (A) 是通过提供的 PendingIntent 通过推送通知启动的。如果这个意图有某个键,那么我需要开始一个新的活动(B)。按回B,我应该回到A。如果我通过开发人员设置启用“不保留活动”,A在启动B后显然会被杀死,这意味着从B返回A时,A会以原来的意图重新创建(其中有额外的密钥) - 再次启动 B - 并导致用户卡在 B 上。

作为一种解决方法,我尝试在启动 B 并重置意图之前删除 A 中的额外键。此代码来自活动 A 中的 onCreate() 方法。我添加了一个 AlarmManager 以轻松复制该行为 - 它与我的问题无关。

    Intent originalIntent = getIntent();
    if(originalIntent != null && originalIntent.hasExtra("A")){
        Log.d(TAG, "onCreate: has A" );
        startActivity(new Intent(this, PAlarmTwo.class));
        originalIntent.removeExtra("A");
        setIntent(originalIntent);
        Log.d(TAG, "onCreate: modified intent has A : " + getIntent().hasExtra("A"));
    } else {
        Log.d(TAG, "onCreate: no A");
    }

    final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            Intent alarmIntent = new Intent(PAlarmOne.this, PAlarmOne.class);
            alarmIntent.putExtra("A", "a");
            PendingIntent pendingIntent = PendingIntent.getActivity(PAlarmOne.this, 1, alarmIntent, 0);
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+1000, pendingIntent);
        }
    });

日志表明,尽管setIntent() 在启动 B 之前删除了密钥,但重新创建的 A 使用该密钥获取了旧意图。基本上,永远不会打印日志(“no A”)。

我尝试过的2个解决方案:

  1. 传递PendingIntent.FLAG_ONE_SHOT 以创建PendingIntent。根据文档,它应该可以工作,但事实并非如此。我对这个标志的理解有误吗?
  2. 在活动 A 中设置一个实例变量,指示该意图是否已被使用过一次。我可以通过onSaveInstanceState() 在外部持久化这个变量,它将在相同活动的重新创建实例中持久化。这种方法感觉不干净,因为它引入了一个新变量来跟踪多个生命周期方法。

【问题讨论】:

    标签: android android-intent android-pendingintent


    【解决方案1】:

    A 显然在启动 B 后被杀死,这意味着从 B 返回到 A 时,A 会以原始意图(具有额外的密钥)重新创建 - 这会再次启动 B - 并导致用户卡在 B .

    您应该在保存的实例状态Bundle 中保存状态,它会告诉您是否应该启动 B。

    日志表明,尽管 setIntent() 在启动 B 之前删除了密钥,但重新创建的 A 使用该密钥获取了旧意图。

    我的猜测是setIntent() 只影响当前实例。它不会向核心操作系统发送指令以以某种方式将这个新的Intent 与 Android 将用于重新创建 A 的回栈记录相关联。

    我对这个flag的理解有错吗?

    该标志控制PendingIntent。它不会影响由 Intent 包裹在 PendingIntent 中的组件。

    这种方法感觉不干净,因为引入了一个新变量来跟踪多个生命周期方法。

    欢迎您发表意见。活动状态涉及很多东西,包括很多可能只需要调用一次的东西(例如,数据加载、确认消息)。这只是另一个。

    【讨论】:

      【解决方案2】:

      本教程对我有用:http://www.helloandroid.com/tutorials/communicating-between-running-activities

       public void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                   setContentView(R.layout.main);
                 processExtraData();
                      }
      
      protected void onNewIntent(Intent intent) {
      super.onNewIntent(intent);
       setIntent(intent);//must store the new intent unless getIntent() will return the old 
      one
      processExtraData()
       }
      
      private void processExtraData(){
      Intent intent = getIntent();
      //use the data received here
      }
      

      【讨论】:

        猜你喜欢
        • 2013-03-03
        • 1970-01-01
        • 2017-05-10
        • 1970-01-01
        • 1970-01-01
        • 2016-07-24
        • 2016-10-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多