Android setIntent() 不会在重新创建的活动中保留新值
Android setIntent() does not persist new value across recreated activities
我的一个 activity (A) 是通过推送通知启动的,通过提供的 PendingIntent。如果这个 intent 有某个键,那么我需要开始一个新的 activity (B)。按回B,我应该return到A。如果我通过开发者设置启用"Don't keep activities",显然A在启动B后被杀死,这意味着在return上从B到A,A是使用原始意图(具有额外的密钥)重新创建 - 再次启动 B - 并导致用户卡在 B 上。
作为解决方法,我尝试在启动 B 并重置意图之前删除 A 中的额外密钥。此代码来自 activity 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个解决方案:
- 通过
PendingIntent.FLAG_ONE_SHOT
创建 PendingIntent
。根据文档,它应该可以工作,但事实并非如此。我对这个标志的理解有误吗?
- 在activityA中设置一个实例变量,指示意图是否已经被使用过一次。我可以通过
onSaveInstanceState()
在外部保留这个变量,它将在相同 activity 的重新创建的实例中保留。这种方法感觉不太干净,因为引入了一个新变量来跟踪多个生命周期方法。
A is obviously killed after launching B, which means on return from B to A, A is recreated with the original intent (which has the extra key) - which launches B again - and it results in the user being stuck on B.
你应该在保存的实例状态中保存状态 Bundle
告诉你是否应该启动 B。
The logs indicate that although setIntent() is deleting the key before launching B, recreated A gets the old intent with the key.
我的猜测是 setIntent()
只影响当前实例。它不会将指令发送回核心 OS 以某种方式将此新 Intent
与 Android 将用于重新创建 A.
的返回堆栈记录相关联
Is my understanding of this flag wrong?
该标志控制 PendingIntent
。它不影响由 Intent
包裹在 PendingIntent
.
中的组件
This approach does not feel clean, for introducing a new variable to track across multiple lifecycle methods.
欢迎您发表意见。 activity 状态涉及很多事情,包括很多可能只需要调用一次的事情(例如,数据加载、确认消息)。这只是另一个。
本教程对我有用: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
}
我的一个 activity (A) 是通过推送通知启动的,通过提供的 PendingIntent。如果这个 intent 有某个键,那么我需要开始一个新的 activity (B)。按回B,我应该return到A。如果我通过开发者设置启用"Don't keep activities",显然A在启动B后被杀死,这意味着在return上从B到A,A是使用原始意图(具有额外的密钥)重新创建 - 再次启动 B - 并导致用户卡在 B 上。
作为解决方法,我尝试在启动 B 并重置意图之前删除 A 中的额外密钥。此代码来自 activity 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个解决方案:
- 通过
PendingIntent.FLAG_ONE_SHOT
创建PendingIntent
。根据文档,它应该可以工作,但事实并非如此。我对这个标志的理解有误吗? - 在activityA中设置一个实例变量,指示意图是否已经被使用过一次。我可以通过
onSaveInstanceState()
在外部保留这个变量,它将在相同 activity 的重新创建的实例中保留。这种方法感觉不太干净,因为引入了一个新变量来跟踪多个生命周期方法。
A is obviously killed after launching B, which means on return from B to A, A is recreated with the original intent (which has the extra key) - which launches B again - and it results in the user being stuck on B.
你应该在保存的实例状态中保存状态 Bundle
告诉你是否应该启动 B。
The logs indicate that although setIntent() is deleting the key before launching B, recreated A gets the old intent with the key.
我的猜测是 setIntent()
只影响当前实例。它不会将指令发送回核心 OS 以某种方式将此新 Intent
与 Android 将用于重新创建 A.
Is my understanding of this flag wrong?
该标志控制 PendingIntent
。它不影响由 Intent
包裹在 PendingIntent
.
This approach does not feel clean, for introducing a new variable to track across multiple lifecycle methods.
欢迎您发表意见。 activity 状态涉及很多事情,包括很多可能只需要调用一次的事情(例如,数据加载、确认消息)。这只是另一个。
本教程对我有用: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
}