Androidでキャッシュディレクトリをクリアするタイミングは?
質問
私は、インターネットから写真を表示するアプリケーションを持っています (デザイナーの仕事のためのショーケース)。私は内部キャッシュディレクトリに私のコンテンツをキャッシュし始めましたが、アプリのコンテンツは、キャッシュサイズで約150MBを取ることができます。また、android のドキュメントによると :
キャッシュファイルは常に自分で管理し、消費される容量の妥当な制限内にとどめるべきです。 1MB などの合理的な容量制限を守ってください。ユーザーがアプリケーションをアンインストールすると、これらのファイルは削除されます。 アプリケーションをアンインストールすると、これらのファイルは削除されます。
そこで、Currents アプリ (Galaxy Nexus) を見てみましたが、アプリケーションのキャッシュ サイズは 110 MB です。しかし、奇妙なことに、Google Currents & Google Maps のようなアプリケーションは、(USB Storage Data) と呼ばれるものにコンテンツをキャッシュしているのです。
では、先ほどのアプリケーションが使っている「USBストレージデータ」とは何なのでしょうか。また、アプリケーションにキャッシュを実装した場合、すべての キャッシュにあるアプリケーションのファイル をループして、何かを挿入するたびにサイズを取得し、比較・クリアするのでしょうか?それとも、Android がアプリケーションのキャッシュ ディレクトリを削除する時期が来たと判断するまで、コンテンツをキャッシュし続けますか?
Androidでキャッシュを管理する流れはどうなっているのか、少なくとも他のアプリケーションが大きなコンテンツをキャッシュするために何をしているのか、とても興味があります。
どのように解決するのですか?
ご質問の前に、2種類のストレージについて簡単に説明します。
キャッシュ
これは、ファイルシステム上のアプリケーション固有のディレクトリです。このディレクトリの目的は、アプリケーションがセッションの間に保持する必要があるかもしれない一時的なデータを保存することですが、それらを永遠に保持することは不可欠ではないかもしれません。通常、このディレクトリにアクセスするには
Context.getCacheDir()
. これは、アプリの設定に "Cache" として表示されます。
ファイル
キャッシュ ディレクトリと同様に、アプリには、ファイルを保持するためのアプリ固有のディレクトリがあります。このディレクトリのファイルは、アプリが明示的に削除するか、アプリがアンインストールされるまで存在します。通常、このディレクトリにアクセスするには
Context.getFilesDir()
. これはアプリの情報画面でさまざまなものとして表示されますが、スクリーンショットではこれは "USB Storage Data" と表示されています。
NOTEです。
明示的に外部メディア(通常はSDカード)に置きたい場合は
Context.getExternalFilesDir(String type)
.
違いについて
どちらのディレクトリも、あなたのアプリケーションにのみ固有のものです (他のアプリケーションはアクセスできません)。キャッシュとファイル ディレクトリの違いの 1 つは、システムがストレージ不足に陥った場合、最初にリソースを解放するのはキャッシュ ディレクトリからであるということです。システムは、files ディレクトリからデータをクリアすることはありません。もう一つの違いは、キャッシュディレクトリは通常、アプリ情報画面から手動でクリアすることができることです。ファイル ディレクトリも通常クリアできますが、ファイル ディレクトリをクリアすると、キャッシュ ディレクトリもクリアされます。
どちらを使用すればよいですか?
それは、そのデータがアプリの寿命と比較してどれほど重要であるかによります。1 回のセッションでデータが必要なだけで、そのデータを再び使用する必要があるかどうか疑わしい場合は、どちらも使用しないでください。不要になるまでメモリに保存しておけばいいのです。複数のセッションでデータを再利用する必要があると思われるが、そのようなことはしない場合 を持つ がない場合、キャッシュディレクトリを使用します。何があってもこのデータが必要な場合、または永続的な保存が必要なかなり大きなデータの場合は、files ディレクトリを使用します。以下は、私が思いつく例です。
-
キャッシュ - 最近開いた電子メール
- 一度開いたデータをキャッシュしておけば、ユーザーがそのメールを再び読みたくなったときに、同じデータを取得するために再びネットワークを使用する代わりに、瞬時に読み込むことができます。最終的にユーザーはそのメールを読み終えるので、これを永遠に保持する必要はありません。
-
ファイル - 電子メールからダウンロードされた添付ファイル
- これは、「必要なときにいつでも呼び出せるように、このデータを保管しておきたい」というユーザーの行動です。したがって、ユーザーが削除を望むまでこのファイルを削除することはないため、files ディレクトリに置きます。
キャッシュ ディレクトリはいつクリアすればよいですか。
キャッシュディレクトリにある
Context.getCacheDir()
javadocs を参照してください。
注意: システムがこれらのファイルを削除してくれることに依存してはいけません。 キャッシュ ファイルで消費する容量には、常に 1 MB などの妥当な最大値を設定する必要があります。 キャッシュ ファイルで消費する容量に 1 MB などの妥当な最大値を設定し、その容量を超えたらファイルを削除する必要があります。 を削除する必要があります。
これは 1 MB の例を使用していますが、それがあなたのアプリケーションにとって妥当かどうかはわかりません。いずれにせよ、ハードな最大値を設定する必要があります。この理由は、単純に、責任あるアプリを設計することに帰着します。では、いつチェックすればよいのでしょうか。私は、キャッシュディレクトリに何かを置きたいと思うたびにチェックすることをお勧めします。以下は、非常にシンプルなキャッシュマネージャです。
public class CacheManager {
private static final long MAX_SIZE = 5242880L; // 5MB
private CacheManager() {
}
public static void cacheData(Context context, byte[] data, String name) throws IOException {
File cacheDir = context.getCacheDir();
long size = getDirSize(cacheDir);
long newSize = data.length + size;
if (newSize > MAX_SIZE) {
cleanDir(cacheDir, newSize - MAX_SIZE);
}
File file = new File(cacheDir, name);
FileOutputStream os = new FileOutputStream(file);
try {
os.write(data);
}
finally {
os.flush();
os.close();
}
}
public static byte[] retrieveData(Context context, String name) throws IOException {
File cacheDir = context.getCacheDir();
File file = new File(cacheDir, name);
if (!file.exists()) {
// Data doesn't exist
return null;
}
byte[] data = new byte[(int) file.length()];
FileInputStream is = new FileInputStream(file);
try {
is.read(data);
}
finally {
is.close();
}
return data;
}
private static void cleanDir(File dir, long bytes) {
long bytesDeleted = 0;
File[] files = dir.listFiles();
for (File file : files) {
bytesDeleted += file.length();
file.delete();
if (bytesDeleted >= bytes) {
break;
}
}
}
private static long getDirSize(File dir) {
long size = 0;
File[] files = dir.listFiles();
for (File file : files) {
if (file.isFile()) {
size += file.length();
}
}
return size;
}
}
もちろん、これは高価な操作になり得るので、バックグラウンドスレッドでのキャッシュを計画する必要があります。
また、これはあなたが必要とするほど複雑になる可能性があります。私の例では、すべてのキャッシュ ファイルがキャッシュ ディレクトリのルートに配置されると仮定しているので、潜在的なサブディレクトリをチェックしません。ファイルを削除するルーチンは、最も古いアクセス日付でファイルを削除するなど、より洗練されたものにすることも可能です。
データをキャッシュすることを決定するときに心に留めておくべきことの 1 つは、キャッシュされたデータがもはや存在しない場合を常に計画する必要があるということです。キャッシュにデータが保存されていない場合、外部手段でデータを取得するための手順を常に用意してください。同様に、外部からデータを取得する前に、必ずキャッシュを確認すること。キャッシュの目的は、ネットワークアクティビティを削減し、長い処理を削減し、アプリで応答性の高いUIを提供することです。ですから、責任を持って使用してください:)
関連
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] ウェブサイト制作のためのChromeキャッシュの無効化
-
[解決済み] アプリケーションを終了することは嫌われますか?
-
[解決済み] gradleのキャッシュをクリアする方法は?
-
[解決済み】「px」、「dip」、「dp」、「sp」の違いは?
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
-
[解決済み] プログラム的に電話をかけるには?
-
[解決済み] Studio 3.4 をアップデートしたら、引数の leftShift() メソッドが見つかりませんでした。
-
[解決済み] 実行に失敗しました app:processDebugResources Android Studio
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 設定ページに移動せずに位置情報サービスをオンにする
-
[解決済み] SDカードからファイルを削除する方法を教えてください。
-
[解決済み] Eclipseでのandroid:configChangesでのAdmobエラー
-
[解決済み] Android Studio - あいまいなメソッド呼び出し getClass()
-
[解決済み] アプリ内課金テスト:android.test.purchased already owned
-
[解決済み] アンドロイドでシェイクを検出するには?
-
[解決済み] アンドロイドのdatepickerダイアログで最大の日付を設定するには?
-
[解決済み] TextView.setTextSizeの挙動がおかしい - テキストビューのテキストサイズを画面ごとに動的に設定する方法
-
[解決済み] edittextのテキストがメールアドレスかどうかを確認するには?
-
[解決済み] ViewPager2でスワイプを無効にするには?