41

私はリストビューでフラグメントを使用しています。このリストビューに関連付けられた ArrayAdapter に、カスタム ローダーで (インターネットから) 受信したデータを入力します。カスタム ArrayAdapter は無限スクロール (ページング) をサポートします。

ユーザーがデバイスを回転させ、ListView でスクロール位置を維持するときに、ArrayAdapter にアイテムを格納する最良の方法は何ですか?

ArrayAdapter で非ビジュアル Fragment を作成し、setRetainInstance メソッドを使用して値を保存することを考えています。

より良い解決策の提案はありますか?

4

6 に答える 6

56

Android フレームワークと Fragment ライフサイクルを操作するonSaveInstanceStateには、Fragment にメソッドを実装する必要があります。簡単にするために、取得できる String 値の配列があると仮定しました (通常、ArrayAdapter を拡張して、ビューの構築をカプセル化し、基になるデータセット全体にアクセスするための便利なメソッドを提供します)。

public void onSaveInstanceState(Bundle savedState) {

    super.onSaveInstanceState(savedState);

    // Note: getValues() is a method in your ArrayAdapter subclass
    String[] values = mAdapter.getValues(); 
    savedState.putStringArray("myKey", values);

}

次に、次のように onCreate メソッド (または onCreateView または onActivityCreated - Fragment JavaDocを参照)でデータを取得できます。

public void onCreate (Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    if (savedInstanceState != null) {
        String[] values = savedInstanceState.getStringArray("myKey");
        if (values != null) {
           mAdapter = new MyAdapter(values);
        }
    }

    ...

}

これにより、デバイスのローテーションやユーザーによる他のアプリケーションへの切り替えなど、データを失うことなく、すべてのライフサイクル イベントが適切に処理されます。メモリを使用しないことonSaveInstanceStateとメモリを使用することの危険性は、Android がそのメモリを再利用する危険性です。保存された状態はこれによって影響を受けませんが、インスタンス変数または非表示のフラグメントを使用すると、データが失われます。

savedStateInstancenull の場合、復元する状態はありません。

これif (values != null)は単に、配列が保存されていない可能性を防ぐためのものですが、ArrayAdapter をコーディングして null データ セットを処理する場合、これは必要ありません。

行が独自のクラスの 1 つのインスタンスであり、単一のデータ項目ではない場合、最終的な解決策は、そのクラスに Parcelable インターフェイスを実装することsavedState.putParcelableArray("myKey", myArray)です。Parcelable の実装方法を知っていると、驚くほど便利です。これにより、インテント内でクラスを渡すことができ、よりクリーンなコードを記述できるようになります。

于 2013-05-29T16:17:21.423 に答える
7

デバイスを回転させると、アプリが再起動されます。アプリonSaveInstanceが破棄される前に呼び出されます。に配列アダプターを保存し、アプリの再起動onSaveInstanceonCreateに最後に が呼び出されると、配列アダプターを取得してリスト ビューに設定できます。

于 2013-05-22T13:53:03.080 に答える
2

オリエンテーションがアクティビティのライフサイクル呼び出しonPauseを変更し、次のonRestart ようなことを行うとき -

@Override
protected void onRestart() {
    super.onRestart();
    mAdapter.getFilter().filter(getFilterSettings());
    mAdapter.notifyDataSetChanged();
}
于 2013-05-26T20:13:35.823 に答える
-1

ArrayAdapterあなたの内容やそれを裏打ちする内容はわかりませんがList、リストを裏打ちするデータをシリアライズ可能にして保存し、ビューが再作成されたときにロードするのはどうですか?

従来、このアプローチは、アプリが閉じられているときにデータを保存しようとしている場合や、バックグラウンドに残っているために強制終了されるリスクがある場合に使用されるのを見てきました。サンプル コードを含むシリアライゼーションに関する素晴らしい投稿がここにあります。カスタム オブジェクトの取得、ArrayListファイルへの書き込み、後で再度開く手順について説明します。このアプローチを実装し、バッキングのデータを書き込むListArrayAdapteronPause()アクティビティが破棄される前に、アクティビティが再作成されたときにそのファイルをリロードできると思います。

その他のアプローチ (別名バックアップ計画):

(1) 簡単だがずさんな - リストが文字列のリストのような基本的なものである場合は、値を個別に書き込み、SharedPreferencesリロード時にそれらを再利用することをいつでも検討できます。保存プロセスで必ず一意の ID を割り当ててください。

これは機能する可能性がありますSharedPreferecnesが、通常、大量のデータを処理するように設計されていないため、リストが長い場合はこのアプローチを避けます. ただし、いくつかのデータ ポイントについては、問題があるとは思えません。

(2) 少し難しいが危険 -Listアダプタに実装されているparcelableか、既にシリアライズ可能なオブジェクトが含まれている場合は、バックグラウンドにある既存のアクティビティにList経由を渡し、コールバックを使用してそのデータを取得することを検討してください。Intent再作成されました。これは、背景を作成するというアイデアに似ていますFragment。どちらのアプローチも、ターゲットにしているActivityまたはがそこにないというリスクがあります。Fragment

于 2013-05-29T15:57:33.227 に答える