从使用navigateUpFromSameTask活动返回()(Returning from an

2019-07-18 12:52发布

我有两个活动,A和B.当活性的第一次启动时,它访问Intent传递给它(因为Bundlenull的,因为它应该通过在第一时间),并相应地显示信息:

CustInfo m_custInfo;
...
protected void onCreate(Bundle savedInstanceState)
{
    ...
    Bundle bundle = (savedInstanceState == null) ? getIntent().getExtras() : savedInstanceState;
    m_custInfo = (CustInfo) m_bundle.getSerializable("CustInfo");
    if (m_custInfo != null
        ...
}

这在第一时间通过工作正常。 该EditText控件和ListView正确填写。

现在,点击列表中的项目时,活动B的开始显示详细信息:

m_custInfo = m_arrCustomers.get(pos);

Intent intent = new Intent(A.this, B.class);
intent.putExtra("CustInfo", m_custInfo); // CustInfo is serializable
// printing this intent, it shows to have extras and no flags

startActivityForResult(intent, 1);

启动acivity B向右之前,框架调用A的重载onSaveInstanceState()

protected void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);

    outState.putSerializable("CustInfo", m_custInfo);
}

在活动B,当按键操作栏中按下时,我想回到活性的,并有其是在相同的状态,因为它以前:

public boolean onOptionsItemSelected(MenuItem item)
{
    if (item.getItemId() == android.R.id.home)
    {
        Intent intent = NavUtils.getParentActivityIntent(this);
        // printing this intent, it shows to have flags but no extras

        NavUtils.navigateUpFromSameTask(this); // tried finish() here but that created an even bigger mess
        return true;
    }
    ...
}

就在这里的问题,在时onCreate()活性A的第二时间,所述Bundle参数是null getExtras()返回null 。 由于onSaveInstanceState()被调用,我本来期望的Bundle参数为非null

我读过有关的其他网站这个问题,已经尝试了建议,但没有任何工程。

Answer 1:

如果你希望你的应用程序反应这样,你应该申报活动为您提供为一体的发射方式:

android:launchMode="singleTop"

在AndroidManifest.xml中。

否则,Android使用标准的推出模式,这意味着

“该系统始终处于目标任务创建活动的新实例”

和你的活动重新创建(参见Android文档 )。

随着singleTop系统返回到您现有的活动(与原来的附加),如果是在任务后面堆栈的顶部。 没有必要在这种情况下实现的onSaveInstanceState。

savedInstanceState你的情况为空,因为你的活动以前没有被关闭的操作系统。

通知 (感谢,用于指向Android开发此 ):

虽然这是问题的解决方案,它不会,如果一个活动返回到是不是上回堆栈的顶部工作。 考虑活动的情况的起始B,这是启动C,和C的父活动被配置为A.如果你调用NavigateUpFromSameTask()从C,活动将被重新创建,因为A是不是在堆栈的顶部。

在这种情况下可以使用这个代码段来代替:

Intent intent = NavUtils.getParentActivityIntent(this); 
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP); 
NavUtils.navigateUpTo(this, intent);


Answer 2:

这是因为NavUtils.navigateUpFromSameTask()基本上只是调用startActivity(intentForActivityA) 如果活动A使用默认android:launchMode="standard"则是创建活动的新实例,而不是使用保存的状态。 有三种方法来解决这个问题,有各种优点和缺点。

选项1

重写getParentActivityIntent()在活动B和指定由活性的所需的适当额外:

@Override
public Intent getParentActivityIntent() {
    Intent intent = super.getParentActivityIntent();
    intent.putSerializable("CustInfo", m_custInfo);
    return intent;
}

注:如果您使用ActionBarActivity和工具栏从支持库,那么你就需要重写getSupportParentActivityIntent() ,来代替。

我觉得这是最优雅的解决方案,因为它的工作原理不论如何导航到活动B.用户下面列出的两个选项无法正常工作,如果用户直接导航到活动B,而无需通过活动以持续,例如,如果活动B从通知或URL处理程序启动。 我认为这种情况是“向上”导航API是复杂的,不是简单地作为一个哑巴后退按钮的原因。

这种解决方案的一个缺点是,标准出发一个全新的活动过渡动画而不是使用返回到先前活动的动画。

选项2

拦截了按钮,并把它作为通过重写一个愚蠢的后退按钮onNavigateUp() :

@Override
public boolean onNavigateUp() {
    onBackPressed();
    return true;
}

注:如果您使用ActionBarActivity和工具栏从支持库,那么你就需要重写onSupportNavigateUp() ,来代替。

该解决方案是一个有点哈克和仅适用于其中“向上”和“后退”应该表现相同的应用程序。 这可能是罕见的,因为如果“向上”和“后退”应该表现一样,那么为什么还要具有上的按钮? 该解决方案的一个优点是,标准回归到以前的活动动画被使用。

选项3

正如yonojoy建议,设置android:launchMode="singleTop"的活动A.见他的答案的详细信息。 需要注意的是singleTop不适合所有的应用程序。 你必须尝试和/或花一些时间阅读文档自己决定。



Answer 3:

而不是调用的NavUtils.navigateUpFromSameTask

你可以得到父母的意图和导航之前对其进行修改。 例如:

Intent intent = NavUtils.getParentActivityIntent(this);
intent.putExtra("CustInfo", m_custInfo); // CustInfo is serializable
NavUtils.navigateUpTo(this, intent);

这将表现得完全一样NavUtils.navigateUpFromSameTask但将让你一些额外的属性添加到意图。 你可以看看的代码NavUtils.navigateUpFromSameTask这是非常简单的。

public static void navigateUpFromSameTask(Activity sourceActivity) {
    Intent upIntent = getParentActivityIntent(sourceActivity);

    if (upIntent == null) {
        throw new IllegalArgumentException("Activity " +
                sourceActivity.getClass().getSimpleName() +
                " does not have a parent activity name specified." +
                " (Did you forget to add the android.support.PARENT_ACTIVITY <meta-data> " +
                " element in your manifest?)");
    }

    navigateUpTo(sourceActivity, upIntent);
}

使得父活动SINGLE_TOP可能对于一些简单的应用程序的工作,但如果这项活动并没有直接从推出它的父? 或者你可能合法地希望家长在后面堆栈多个地方存在。



Answer 4:

我认为这是一个更通用的解决方案,被添加到您的基本活动类:

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        final Intent upIntent = NavUtils.getParentActivityIntent(this);
        if (upIntent == null)
            onBackPressed();
        else
            //optionally add this flag to the intent: Intent.FLAG_ACTIVITY_SINGLE_TOP
            NavUtils.navigateUpTo(this, upIntent);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

为此,你希望将导航到一些特定父活动的每个活动,使用的清单:

    <activity android:parentActivityName="pathToParentActivity" ...>
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="pathToParentActivity"/>
    </activity>

而且,如果你的minSdk是API 16,去掉“元数据”的标签,让你有这一句的清单:

    <activity android:parentActivityName="pathToParentActivity" ...>
    </activity>

更多信息点击这里



Answer 5:

你提到:

在活动B,当按键操作栏中按下时,我想回到活性的,并有其是在相同的状态,因为它以前。

如果您对活动的含量存在于一个片段,然后调用片段的setRetainInstance(真)在OnCreate()。

然后将片段实例将跨越活动娱乐被保留。



文章来源: Returning from an activity using navigateUpFromSameTask()