69

AとBの2つのアクティビティがあります。アクティビティAが最初に開始されると、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);

アクティビティBが開始される直前に、フレームワークはAのオーバーライドを呼び出しますonSaveInstanceState()

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

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

アクティビティBで、アクションバーの[上へ]ボタンが押されたときに、アクティビティAに戻り、以前と同じ状態にします。

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が2回目に入ると、Bundleパラメータはであり、を返します。呼び出されてから、パラメータが非であると予想していました。null getExtras()nullonSaveInstanceState()Bundlenull

私は他のWebサイトでこの問題について読み、提案を試しましたが、何も機能しません。

4

5 に答える 5

21

これは、NavUtils.navigateUpFromSameTask()基本的に を呼び出すだけで発生しますstartActivity(intentForActivityA)。アクティビティ A がデフォルトandroid:launchMode="standard"を使用する場合、アクティビティの新しいインスタンスが作成され、保存された状態は使用されません。これを修正するには 3 つの方法があり、さまざまな長所と短所があります。

オプション1

アクティビティ B でgetParentActivityIntent()をオーバーライドし、アクティビティ A に必要な適切なエクストラを指定します。

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

注: AppCompatActivity と androidx またはサポート ライブラリのツールバーを使用している場合は、代わりにgetSupportParentActivityIntent()をオーバーライドする必要があります。

これは、ユーザーがアクティビティ B に移動した方法に関係なく機能するため、最も洗練されたソリューションだと思います。以下に示す 2 つのオプションは、ユーザーがアクティビティ A を経由せずに直接アクティビティ B に移動した場合、正しく機能しません。 B は、通知または URL ハンドラーから起動されます。このシナリオが、「上」ナビゲーション API が複雑であり、単純に戻るボタンとして機能しない理由だと思います。

このソリューションの欠点の 1 つは、前のアクティビティに戻るアニメーションではなく、標準の新しいアクティビティを開始する遷移アニメーションが使用されることです。

オプション 2

上ボタンをインターセプトし、 onNavigateUp()をオーバーライドして、ダムの戻るボタンとして扱います。

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

注: AppCompatActivity と androidx またはサポート ライブラリのツールバーを使用している場合は、代わりにonSupportNavigateUp()をオーバーライドする必要があります。

このソリューションは少しハックで、「up」と「back」が同じように動作する必要があるアプリケーションでのみ機能します。「上へ」と「戻る」が同じように動作するはずなのに、わざわざ上ボタンを用意する必要があるので、これはおそらくまれです。このソリューションの利点の 1 つは、前のアクティビティに戻る標準のアニメーションが使用されることです。

オプション 3

yonojoy が提案したように、android:launchMode="singleTop"アクティビティ A に設定します。詳細については、彼の回答を参照してください。singleTopすべてのアプリケーションに適しているわけではないことに注意してください。試してみるか、ドキュメントを読んで自分で決める必要があります。

于 2014-11-06T22:00:51.780 に答える
4

呼び出す代わりに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 にすることは、一部の単純なアプリケーションではうまくいくかもしれませんが、このアクティビティがその親から直接起動されていない場合はどうなるでしょうか? または、親がバックスタックの複数の場所に存在することを合法的に望むかもしれません。

于 2014-12-19T05:09:06.320 に答える
-1

あなたは言及します:

アクティビティBで、アクションバーの上へボタンが押されたら、アクティビティAに戻って元の状態にしたいです。

アクティビティ A のコンテンツがフラグメントにある場合は、フラグメントの onCreate() で setRetainInstance(true) を呼び出します。

その後、Fragment インスタンスは、Activity の再作成全体で保持されます。

于 2014-02-17T22:00:17.190 に答える