Androidでの静的変数の使用は、特にアクティビティを参照する場合は非常に危険です。しかし、Applicationを拡張するクラスがある場合(このクラスを「App」と呼びましょう)、このクラスのインスタンスを参照しても安全ですか?
もしそうなら、他のクラスがアプリケーションコンテキストへのあらゆる種類の参照を持つことは安全ですか?つまり、任意の種類のクラスでアプリケーションコンテキストへの参照がある場合、メモリリークが発生する可能性がありますか?
目的は、どのスコープにいても、常にアプリケーションコンテキストへの参照を取得できることです。システムがアプリケーションを閉じると、静的変数も次回アプリケーションが再起動するまで消えてしまうため、安全だと思います。これにより、静的変数が再び初期化されます。
また、それほど重要ではありませんが、複数のプロセスを使用する場合、各プロセスでAppクラスへのまったく異なる参照を取得しますか?
コードの例として、私が考えているのは次のとおりです。
public class App extends Application
{
private static Context _appContext;
@Override
public void onCreate()
{
super.onCreate();
_appContext = this;
}
public static Context getAppContext()
{
return _appContext;
}
}
アプリコンテキストを静的変数に保存しても安全ですか?
現在、はいは安全であるように見えますが、getAppContext()
return Context
ではなくApp
またはApplication
を返します。
そうは言っても、コアAndroidチームが最初にこのように設定しなかったという事実は、おそらく私たちが知らない、または将来的にそれが隠された問題があるかもしれないことを示唆していますこのアプローチでは問題が発生する可能性があります。
格言の頭字語が行くように、 [〜#〜] ymmv [〜#〜] 。 :-)
[〜#〜]編集[〜#〜]
もしそうなら、他のクラスがアプリケーションコンテキストへのあらゆる種類の参照を持つことも安全ですか?
ここで「安全」とはどういう意味かわかりません。
しかし、複数のプロセスを使用する場合、各プロセスでAppクラスへのまったく異なる参照を取得しますよね?
複数のプロセスを使用する場合は、マスで平手打ちする必要があります。しかし、はい、プロセスごとに異なるApp
インスタンスを取得する必要があります。
安全なはずです。また、 API docs からの次のメモも参考になります。
通常、
Application
をサブクラス化する必要はありません。ほとんどの状況で、静的シングルトンは、よりモジュール的な方法で同じ機能を提供できます。シングルトンにグローバルコンテキストが必要な場合(たとえば、ブロードキャストレシーバーを登録するため)、それを取得する関数に、シングルトンを最初に構築するときに内部でContext.getApplicationContext()
を使用するコンテキストを指定できます。
Application
はアクティビティの前に作成されるため、Application#onCreate()
でこれを行うのが安全です。アプリがバックグラウンドで強制終了されると、Application
インスタンスが再作成され、アクティビティが実行される前にグローバルが設定されます。
アクティビティからグローバル変数を設定してはならないことに注意してください。その場合、アプリは次のように失敗する可能性があります。
NullPointerException
厄介な静的コンテキストを片付けているときに、スタジオから興味深いコメントがポップアップ表示されました。
「これはリークです(また、Instant Runを壊します)。」
つまり、Instant Runの起動に伴い、Android=開発者が静的変数の保存を計画していない場合があります。InstantRunは(まだ)議題に含まれていませんが、それが悪い習慣であるだけでなく、それが間違っているユースケースが特定される特定の例があります。
これは、Android-studioでContext context;
を作成するときの警告です。
Androidコンテキストクラスを静的フィールドに配置しないでください。これはメモリリークであり、Instant Runも中断します。
静的フィールドはコンテキストをリークします。
非静的内部クラスには、外部クラスへの暗黙的な参照があります。
その外部クラスが例えばフラグメントまたはアクティビティである場合、この参照は、実行時間の長いハンドラー/ローダー/タスクが、ガベージコレクションが実行されないようにするアクティビティへの参照を保持することを意味します。同様に、これらの長時間実行インスタンスからのアクティビティとフラグメントへの直接フィールド参照は、リークを引き起こす可能性があります。
ViewModelクラスは、ビューまたは非アプリケーションコンテキストを決して指すべきではありません。