Android Applicationクラスを使用してデータを永続化する


112

私はかなり複雑なAndroidアプリケーションに取り組んでいます。このアプリケーションについては、アプリケーションに関するやや大量のデータが必要です(合計で約500KBになると思います-モバイルデバイスの場合、これは大きいですか?)。私が知ることができることから、アプリケーション(アクティビティ内、より正確には)の方向の変更は、アクティビティの完全な破棄と再現を引き起こします。私の調査結果に基づくと、Applicationクラスには同じライフサイクルがありません(つまり、すべての意図および目的のために、常にインスタンス化されます)。アプリケーションクラス内に状態情報を格納してからそれをアクティビティから参照することは理にかなっていますか。それとも、モバイルデバイスのメモリの制約により、一般的に「受け入れ可能な」メソッドではありませんか?私はこのトピックについてのアドバイスを本当に感謝しています。ありがとう!


8
ただし、アプリがバックグラウンドになった場合でも、アプリケーション内のデータは削除される可能性があるため、これは常に取得できるようにしたいデータを永続化するためのソリューションではありません。これは、高価なオブジェクトを頻繁に再作成する必要がない方法として機能します。
シェリルサイモン

2
マイラ; アプリは「通常」削除されているとは思いません(ただし、誰かがこのスレッドで後で指摘しているように、「できる」とは言えません)。おそらく、アプリケーションを使用してデータを格納およびロードする「ハイブリッド」アプローチの種類を使用しますが、マニフェストファイルのアクティビティで「android:orientation」属性を使用して、アクティビティを分解して再構築します。もちろん、これらすべては、データが永続化できるように、アプリケーションが破棄される「時期」を判別できることを前提としています。
Dave、

回答:


134

500kbはそれほど大きな問題になるとは思いません。

あなたが説明したのは、アクティビティでデータを失うという私の問題にどのように取り組んだかです。Applicationクラスでグローバルシングルトンを作成し、使用したアクティビティからアクセスできました。

データが頻繁に使用される場合は、グローバルシングルトンでデータを渡すことができます。

public class YourApplication extends Application 
{     
     public SomeDataClass data = new SomeDataClass();
}

次に、次の方法でアクティビティで呼び出します。

YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here.

これについては、ブログ記事の「グローバルシングルトン」セクションで説明します。


1
残念ながら、問題のブログ投稿はそのアドレスでは利用できなくなりました。
mikebabcock 2014年

1
私は自分のサイトで物事を移動しています。それが固定されるまで、あなたはここでarchive.orgでそれを見つけることができます:web.archive.org/web/20130818035631/http://www.bryandenny.com/...
ブライアン・デニー

1
私はこれが古い投稿であることを知っていますが、これで解決できる問題に遭遇しましたが、このクラスはマニフェストで何らかの方法で宣言する必要があります。私はクラスをacssesできないので、これが私が欠けているものだと感じます...
Ziv Kesten 14年

1
@ZivKesten name =属性をマニフェスト内のアプリケーションタグに追加しませんか?
MikeC 2014

@mgcしばらくの間ありがとうございました。そうです、それで私は最終的にそれを解決しました。また、このクラスへのキャストでgetApplicationContext()を与えることにより、必要なところにそのクラスのインスタンスを作成しました
Ziv Kesten

57

Applicationインスタンスを当てにする人は間違っています。最初は、Applicationアプリプロセス全体が存在する限り存在するように見えるかもしれませんが、これは誤った仮定です。

OSは必要に応じてプロセスを強制終了する場合があります。すべてのプロセスは、ドキュメントで指定された5つのレベルの「killability」に分類されます

したがって、たとえば、ユーザーが着信呼び出しに応答したためにアプリがバックグラウンドで実行された場合、RAMの状態に応じて、OSがプロセスを強制終了する(またはしない)(Applicationプロセス内のインスタンスを破棄する) 。

データを内部ストレージファイル永続化し、アクティビティが再開したときにそれを読み取るのが、より良いアプローチだと思います。

更新:

私は多くの否定的なフィードバックを得たので、説明を加える時がきました。:)まあ、私は本当に状態がアプリにとって本当に重要であるという誤った仮定を本当に使いました。ただし、アプリに問題がなく、状態が失われる場合があります(再読み込み/再ダウンロードされる画像がある可能性があります)。アプリをのメンバーとして保持しても問題ありませんApplication


14
アプリケーションが強制終了された場合、誰が気にかけますか?アプリケーションはなくなりました。私が理解しているように、Androidはアクティビティなどのメモリを含むプロセスを再利用します。アプリケーションを含むプロセスが強制終了された場合(Androidがそれを行う場合でも?)、それは本質的にアプリを強制終了したようなものです。ユーザーはアプリを再度起動する必要があり、その時点で誰が気にかけますか?これは、アプリケーションの新しいインスタンスです。
Andrew、

14
これは、私たちの生産にとって不愉快な驚きでした。Androidがプロセスを強制終了すると思いますが、これはRAMの状態やドキュメントに記載されているその他の要因に依存します。それは私たちにとって悪夢だったので、私は実際の経験を共有します。エミュレータにはこれがありませんでしたが、実際には一部のデバイスがアプリで「過負荷」になっているため、バックグラウンドプロセスを強制終了することは通常の状況です。はい、ユーザーがアプリをフォアグラウンドにすることを決定した場合-OSはApplicationインスタンスを含むスタックを復元しますが、永続化しない限り、信頼できる静的データはありません。
Vit Khudenko、2010年

2
多分ハイブリッドなアプローチを使うつもりだと思います。方向の変更をオーバーライドするマニフェストトリックについては既に知っていました(他の利点もあります)。アプリケーションはゲームなので、起動と起動の間にデータを保持することが「重要」であるかどうかはわかりません。ほとんどのデータはシリアル化できるため、おそらくそれほど難しくはありません(ただし、方向の変更ごとにシリアル化したり、シリアル化を解除したりする必要はありません)。私は間違いなく入力を感謝しています。Appインスタンスに依存するものは「間違っている」とは言えません。多くはアプリに依存します:)。
デイブ、

1
@Arhimed回答を一般化しすぎています。そして、あなたの仮定に基づいて狭いアプローチを提案します。誤った仮定:静的変数に保持されているデータは、アプリのセッション全体で保持される必要があります。データが取るに足らないものであり、すぐに永続化する必要がないユースケースは数多くあります。
Mandar Limaye、2012年

2
構造が複雑な約1MBのデータがあります。デバイスが作業で過負荷になると、シリアライズ/デシリアライズで最大2〜3秒かかる可能性があります。アクティビティ間の保存/読み込みのアイデアは、時間がかかりすぎます。アプリケーションをストレージとして使用します。もちろん、アプリケーションインスタンスに格納されている私のデータクラスはすべてのメソッドをチェックします-データはまだ生きているか、ロードする必要があります。したがって、Daveは次のことを行う必要があります。1.ロード/ save機能を提供する2.アプリケーションにデータを保持する。3.アクセスデータのトリプルチェックロジック。
Kostadin 2012

6

アクティビティの外部で「グローバルシングルトン」にアクセスしContext、関連するすべてのオブジェクトを通過させてシングルトンを取得したくない場合は、アプリケーションクラスで静的属性を定義するだけで、自体。onCreate()メソッドの属性を初期化するだけです。

例えば:

public class ApplicationController extends Application {
    private static ApplicationController _appCtrl;

    public static ApplicationController getAppCtrl()
    {
         return _appCtrl;
    }
}

のサブクラスApplicationもリソースを取得できるため、次のようにそれらを返す静的メソッドを定義するときに、それらに簡単にアクセスできます。

public static Resources getAppResources()
{
    return _appCtrl.getResources();
}

ただし、メモリリーク回避するために、コンテキスト参照を渡すときは十分に注意してください


6
クラスをインスタンス化するには、マニフェストにandroid:name = "。ApplicationController" xml属性のアプリケーションタグを追加する必要があることに注意してください。
eggie5 2012年

これを行うために実際に拡張Applicationする必要はありません。これを行うには、任意のクラスで静的メンバー変数を宣言できます。
David Wasser 2017

2

デイブ、それはどんなデータですか?アプリケーション全体に関連する一般的なデータ(例:ユーザーデータ)の場合は、Applicationクラスを拡張してそこに格納します。データがアクティビティに関連する場合は、onSaveInstanceStateハンドラーとonRestoreInstanceStateハンドラーを使用して、画面回転時にデータを永続化する必要があります。


データがParcelに格納するのに本当に大きい場合はどうなりますか?これは私が得ているものです:android.os.TransactionTooLargeException:データパーセルサイズ838396バイト
Arjun

1

実際に向きの機能をオーバーライドして、アクティビティが破棄されて再作成されないようにすることができます。見てここに


16
多くのことができます。それが良いアイデアだという意味ではありません。これは良い考えではありません。
Andrew

画面の向きを変更してテストすることは、Androidが想定していることをアプリが実行することを確認する最も簡単な方法です。
18446744073709551615 2013年

0

アプリケーションクラスを作成し、その計算に関するすべてのデータを保存して、アプリケーションの任意の場所で使用できます。


0

私はこれが非常に古い問題であることを知っていますが、jetpackコンポーネントからViewModelを使用することが、アクティビティローテーション間でデータを保持するための最良の方法です。

ViewModelクラスは、ライフサイクルを意識した方法でUI関連のデータを格納および管理するように設計されています。ViewModelクラスを使用すると、データを画面の回転などの構成変更に耐えることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.