onSavedInstanceStateの例の使用方法


110

状態を保存することになると私は混乱しています。つまりonSaveInstanceState(Bundle)、アクティビティが破棄されようとしているときに呼び出されます。しかし、どのようにして情報を保存し、元の状態に戻すのonCreate(Bundle savedInstanceState)ですか?このバンドルがどのように情報を復元するのかわかりません。誰かが例を提供できると助かります。開発ガイドはこれをうまく説明していません。

public class Conversation extends Activity {
    private ProgressDialog progDialog;
    int typeBar;
    TextView text1;
    EditText edit;
    Button respond;
    private String name;
    private String textAtView;
    private String savedName;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.dorothydialog);
        text1 = (TextView)findViewById(R.id.dialog);
        edit = (EditText)findViewById(R.id.repsond);
        respond = (Button)findViewById(R.id.button01);

        if(savedInstanceState != null){
            savedInstanceState.get(savedName);
            text1.setText(savedName);
        }
        else{
            text1.setText("Hello! What is your name?");
            respond.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    name = edit.getText().toString();
                    text1.setText("Nice to meet you "+ name);
                }   
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putString(savedName, name);
    }
}

text1.setText(savedInstanceState.getString(savedName));
Spidy

@Spidy onBackpressedはどうですか?バンドルでこれにどのように反応しますか?
tjウォーカー

あなたはしません。ユーザーが戻るボタンを押したとき。アクティビティは強制終了されます。データベースを永続的なデータストレージとして使用します。バンドルを使用して、再起動されたアプリケーションを以前の状態に戻します。
Spidy

回答:


198

Bundle保存したいすべての情報のコンテナです。put *関数を使用して、データを挿入します。以下は、データをに格納するために使用できるput関数の短いリストです(より多くあります)Bundle

putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)

あなたのonCreate関数では、これBundleはプログラムに渡されます。アプリケーションがリロードされているか、初めて起動されているかを確認する最良の方法は次のとおりです。

if (savedInstanceState != null) {
    // Then the application is being reloaded
}

データを元に戻すには、put *関数と同じようにget *関数を使用します。データは名前と値のペアとして格納されます。これはハッシュマップのようなものです。キーと値を指定し、値を戻したい場合はキーを指定すると、関数が値を取得します。これが短い例です。

@Override
public void onSaveInstanceState(Bundle outState) {
   outState.putString("message", "This is my message to be reloaded");
   super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String message = savedInstanceState.getString("message");
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}

保存したメッセージは画面にトーストされます。お役に立てれば。


14
onSaveInstanceState()は、アクティビティが一時停止される前に呼び出されます。したがって、破壊される可能性のある後に必要な情報は、保存されたバンドルから取得できます
Diederik

@スパイディすごい!あなたは本当に私にバンドルに関するすべてを理解させました!だから、outStateがsavedInstanceStateバンドルに戻されると思いますか?正しい?
tjウォーカー

うん。outStateバンドルは、savedInstanceState Bundleとして渡されます
Spidy

1
@tj walker-もう1つの優れたリソースは、テクニカルリファレンスブックです。Pro Android 3は、Amazonで入手できる安価で豊富なリソースです
Spidy

@Spidy私はあなたが見るために上記の私の活動コードを投稿しました。多分あなたはあなたが提案したように、私が私の状態を正しく保存しているかどうか私に知らせることができます。
tjウォーカー

34

すべての新しいAndroid開発者が知っておくべき重要な注意点の1つは、ウィジェットのすべての情報(TextView、ボタンなど)は、IDを割り当てる限り、Androidによって自動的に永続化されるということです。つまり、ほとんどのUI状態は問題なく処理されます。他のデータを保存する必要がある場合のみ、これが問題になります。

Androidドキュメントから:

必要な作業は、状態を保存する各ウィジェットに一意のID(android:id属性を指定)を提供することだけです。ウィジェットにIDがない場合、その状態を保存できません


1
まあそれは本当に本当ですか?ボタンtextviewと編集テキストのあるアクティビティがあるからです。アプリケーションが破棄または強制終了されると、すべてが元の状態に戻ります。私のアプリケーションでは、ユーザーがボタンをクリックするたびにtextViewテキストが変更されます。
tjウォーカー

ドキュメントは不正確ですか?ビューで独自の情報を保存したことはありません。あなたの最善の策は、私の意見ではすべての情報を自分で保存することです。
Spidy

2
onSaveInstanceStateが情報を保存することである場合は、その場所ではありません。これは、呼び出される保証がないためです(ドキュメントを参照)。代わりに、データベース、SharedPreferencesなどに書き込む必要があります。はい、この情報は正確です。UIがこのように持続するかどうかをテストする最良の方法は、方向の変更に応じてディスプレイを回転させ、onCreateを再実行し、バンドルを使用して状態を復元することです。
キースアドラー

@日産ファンはあなたが上記の気の利いたように例を示すことができますか?sharedprefsとすべてで?ありがとう
tj walker

率直に言って、最良の例はドキュメントにあります。 developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler

6

良い情報:onCreate()メソッドでBundleオブジェクトがnullであるかどうかを確認する必要はありません。システムがonStart()メソッドの後に呼び出すonRestoreInstanceState()メソッドを使用します。システムはonRestoreInstanceState()を呼び出すのは、復元する保存済みの状態がある場合のみなので、バンドルがnullであるかどうかを確認する必要はありません。


5

店舗情報:

static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(PLAYER_SCORE, mCurrentScore);
    savedInstanceState.putInt(PLAYER_LEVEL, mCurrentLevel);

// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

onCreate-Methodの情報を復元したくない場合:

次に例を示します。アクティビティの再作成

onCreate()中に状態を復元する代わりに、システムがonStart()メソッドの後に呼び出すonRestoreInstanceState()の実装を選択できます。システムはonRestoreInstanceState()を呼び出すのは、復元する保存済みの状態がある場合のみなので、バンドルがnullであるかどうかを確認する必要はありません。

public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);

// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}

0

基本的に、onSaveInstanceState(Bundle outBundle)はバンドルを提供します。Bundleクラスを見ると、たくさんの異なるものをその中に入れることができることがわかります。onCreate()の次の呼び出しでは、そのバンドルを引数として返すだけです。その後、値を再度読み取り、アクティビティを復元できます。

EditTextを含むアクティビティがあるとします。ユーザーはその中にテキストを書きました。その後、システムはonSaveInstanceState()を呼び出します。EditTextからテキストを読み取り、Bundle.putString( "edit_text_value"、theValue)を介してバンドルに書き込みます。

今度はonCreateが呼び出されます。提供されたバンドルがnullでないかどうかを確認します。その場合は、Bundle.getString( "edit_text_value")を使用して値を復元し、EditTextに戻すことができます。


0

これは追加情報です。

このシナリオを想像してください

  1. ActivityAがActivityBを起動します。
  2. ActivityBが新しいActivityAPrimeを起動します

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
  3. ActivityAPrimeはActivityAとは関係ありません。
    この場合、ActivityAPrime.onCreate()のバンドルはnullになります。

ActivityAとActivityAPrimeが異なるアクティビティではなく同じアクティビティである必要がある場合、ActivityBはstartActivity()を使用するよりもfinish()を呼び出す必要があります。


明確にするために、あなたの例では、ActivityA == ActivityAインスタンス1およびActivityAPrime == ActivityAインスタンス2ですか?また、「ActivityBはstartActivity()を使用するよりもfinish()を呼び出す必要があります。」つまり:(1)AcitivityBはfinish()を呼び出し、その後startActivity()を使用する必要があります(2)またはActivityBはstartActivity()を使用するのではなく、finish()を呼び出す必要がありますか?オプション2を意味する場合、誰かが同じactivityA instance1を再起動して、破棄/終了する前に含まれているアクティビティのデータをロードできるようにするにはどうしたらよいでしょうか?ありがとう
cjayem13 2014

ActivityAとActivityAPrimeは同じクラスですが、インスタンスが異なります。このシナリオでは、ActivityAはまだビジネスを完了していません。その途中で、ActivityBを作成して開始したため、ActivityBが完了すると、ActivityAは残りのビジネスを継続する必要があります。この場合、startActivityを呼び出すのは間違っており、ActivityAとActiviyAPrimeが同じインスタンスであると想定しています。したがって、ActivityAを再起動するのではなく、ActivityBを終了して、ActivityAに操作を再開させます...
ken

0

データが読み込まれない場合は、savedInstanceState次のコードを使用します。
問題は、URL呼び出しが完全には完了しないことです。データがロードされているかどうかを確認してから、instanceState値を表示してください。

//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
    mAlreadyLoaded = true;
    GetStoryData();//Url Call
} else {
    if (listArray != null) {  //Data Array From JsonArray(ListArray)
        System.out.println("LocalData  " + listArray);
        view.findViewById(R.id.progressBar).setVisibility(View.GONE);
    }else{
        GetStoryData();//Url Call
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.