転載元:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1209/2136.html
オフラインキャッシュとは、ネットワークのブロックが解除されたときにサーバーから受信したデータをローカルに保存し、ネットワークが切断されたときにローカルファイルのデータを直接読み取ることです。
ネットワークデータをローカルに保存する:
データをローカルファイルとして保存し、Androidシステムの任意のディレクトリに保存するメソッドを作成できます(もちろん、許可されています)が、この場合、最も簡単に使用できます。コンテキストのopenFileOutputメソッドこれもこのシナリオに最も適しています。次のsaveObjectメソッドは、openFileOutputを使用してローカルファイルにデータを保存する方法を示しています
。saveObject
public static boolean saveObject(Serializable ser, String file) {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = AppContext.getInstance().openFileOutput(file, AppContext.getInstance().MODE_PRIVATE);
oos = new ObjectOutputStream(fos);
oos.writeObject(ser);
oos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
oos.close();
} catch (Exception e) {
}
try {
fos.close();
} catch (Exception e) {
}
}
}
openFileOutputは、アプリケーションに関連付けられたファイルパス(/ data / data / <パッケージ名> / filesの下)を直接取得し、java ioのObjectOutputStreamを使用して、取得したファイルにシリアル化されたオブジェクト(writeObject)を書き込むことができます。上記の実装プロセスには、openFileOutput、writeObject、およびそれらを呼び出す2つのキーオブジェクトContextとObjectOutputStreamの2つのキーメソッドがあります。シリアル化については、次の記事を参照してください:Javaオブジェクトのシリアル化と逆シリアル化の実践
これは、シリアル 化されたオブジェクトをローカルに保存することです。ネットワークデータを格納するためのオフラインキャッシュとは何の関係がありますか?
オンラインで取得したデータのほとんどは文字列型の文字列に変換できるため、サーバーから返されるデータは通常json形式の文字列であるため重要です。文字列のStringタイプは、実際にはシリアル化可能なオブジェクトです。以下は、サーバー(実際にはjcodecraeer)によって返されるjsonデータの例です。
{"url":"http://jcodecraeer.com/uploads/soft/android/CodeBox.apk","versionCode":"7","updateMessage":"增加离线缓存,分类筛选功能修正了版本兼容性问题 "}
上記のsaveObjectメソッドを使用して、データをローカルに保存できます。このファイルを取得できるようにするには、保存したファイルに名前を付ける方法を理解する必要があります。記事のデータだけの場合は、直接名前を付けることができます。 file as this記事のID。IDは一意であるため、他のデータとできるだけ競合しないように、このIDの前にプレフィックスを追加することもできます。たとえば、この記事はjava列の下にあります。このarc_java_idを実行できます。記事リストの場合は、article category_page numberのように名前を付けることができます。つまり、名前の原則は、他のオフラインデータと区別し、一意にすることです。ファイル名としてURLを使用してみませんか?URLは一意である必要がありますが、URLは必ずしもファイルの命名規則に準拠しているとは限りません。
ここでは、ローカルキャッシュデータの
読み取りキャッシュを読み取る方法を説明 します。ファイル名を知る必要がある場合は、次のreadObjectメソッドを使用して、ファイル名に基づいてキャッシュデータを読み取ります。実際、多くのものが上記で保存されたデータに対応しています。
readObject
/**
* 读取对象
*
* @param file
* @return
* @throws IOException
*/
public static Serializable readObject(String file) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = AppContext.getInstance().openFileInput(file);
ois = new ObjectInputStream(fis);
return (Serializable) ois.readObject();
} catch (FileNotFoundException e) {
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (Exception e) {
}
try {
fis.close();
} catch (Exception e) {
}
}
return null;
}
使用
次のコードは、格納およびデータネットワークを読んで上記の知識を使用する方法を示します
String key = "codelist_" + mCategory.getValue() + "_" + + page ;
String result = "";
//cache
if (HttpUtil.isNetworkConnected()) {
result = HttpUtil.http_get(AppContext.getInstance(), url );
HttpUtil.saveObject(result, key);
result = (String) HttpUtil.readObject(key);
} else {
result = (String) HttpUtil.readObject(key);
if (result == null)
result = "erro";
}
ネットワークのブロックが解除されている場合は、サーバーからデータを取得し(HttpUtil.http_get(AppContext.getInstance()、url))、データをローカルに保存し(HttpUtil.saveObject)、ネットワークが利用できない場合は、キャッシュされたデータをから直接読み取ります。ローカル、サーバーと対話しません。
前記HttpUtilは、それは、3つの方法に関与するネットワークツールに関連付けられている。
)isNetworkConnected(ネットワークが利用可能であるか否かを判断
達成上方saveObject与えられた
上で与えられたのreadObject実装
HTTP_GET URLサーバが指定されたデータを読み出し
及びAppContextを.getInstance()でありますHttpUtilの静的メソッドでContextオブジェクトを取得しやすくするために自分で作成しました。
ここで重要なのはファイル名です。
追加の要件が
あり、場合によってはそのような要求があります。ユーザーが指定された時間間隔内に、ネットワークから取得したこの時間間隔でローカルから同じデータソースを読み取る場合、目的はユーザーのトラフィックを節約することですが、毎回ネットワークからデータを取得することによって引き起こされるインターフェイスの遅延。
以下は、時間間隔に従ってサーバーデータを更新する必要があるかどうかを判断する方法です。trueは不要、falseは必須を意味します(非常に厄介ですが、isCacheDataFailureの命名に関連しています)。
public static boolean isCacheDataFailure(String cachefile) {
boolean failure = false;
File data = AppContext.getInstance().getFileStreamPath(cachefile);
if (data.exists()
&& (System.currentTimeMillis() - data.lastModified()) > CACHE_TIME)
failure = true;
else if (!data.exists())
failure = true;
return failure;
}
現在の時刻をファイルの変更時刻と比較します。CACHE_TIMEは固定値(ミリ秒)であり、任意のint型に置き換えることができます。
この判定条件を追加し、上記のコードを次のように変更します。
String key = "codelist_" + mCategory.getValue() + "_" + + page ;
String result = "";
//cache
if (HttpUtil.isNetworkConnected() && HttpUtil.isCacheDataFailure(key)) {
result = HttpUtil.http_get(AppContext.getInstance(), url );
HttpUtil.saveObject(result, key);
result = (String) HttpUtil.readObject(key);
} else {
result = (String) HttpUtil.readObject(key);
if (result == null)
result = "erro";
}
一般的なアプリケーションについては上記の手順を完了 するだけで十分ですが、需要が高い場合は、時間が経つにつれてキャッシュされるデータが増えることを考慮する必要があるため、期限切れのキャッシュ機能の削除を追加する必要があります。原則は、しきい値。キャッシュを保存するときに、現在のキャッシュの合計量がしきい値より大きいかどうかを判断し、大きい場合は、前のキャッシュを削除します。
これは実装が少し複雑です。より簡単な解決策を検討し、キャッシュの合計量を定期的に(またはユーザーがプログラムを開くたびに)チェックし、しきい値を超えた場合は、ユーザーに積極的に削除するように促します。具体的な実装についてはあまり触れません。
注:openFileOutput()メソッドの最初のパラメーターはファイル名を指定するために使用され、パス区切り文字「/」を含めることはできません。ファイルが存在しない場合、Androidは自動的にファイルを作成します。作成されたファイルは、Eclipseメニューの[ウィンドウ]-"をクリックして、/ data / data / <パッケージ名> / filesディレクトリ(/data/data/cn.itcast.action/files/itcast.txtなど)に保存されます。 [ビューの表示]-[その他]、ダイアログウィンドウでandroidフォルダーを展開し、下のファイルエクスプローラービューを選択してから、ファイルエクスプローラービューで/ data / data / <パッケージ名> / filesディレクトリを展開してファイルを表示します。
openFileOutput()メソッドの2番目のパラメーターは、操作モードを指定するために使用されます。4つのモードがあります。つまり、Context.MODE_PRIVATE = 0
Context.MODE_APPEND = 32768
Context.MODE_WORLD_READABLE = 1
Context.MODE_WORLD_WRITEABLE = 2
Context.MODE_PRIVATE:これはデフォルトの操作モードです。つまり、ファイルはプライベートデータであり、アプリケーション自体からのみアクセスできます。このモードでは、書き込まれたコンテンツが元のファイルのコンテンツを上書きします。追加する場合元のファイルに新しく書き込まれたコンテンツ。Context.MODE_APPENDを使用できます。Context.MODE_APPEND
:モードは、ファイルが存在するかどうかを確認し、存在する場合はファイルにコンテンツを追加します。存在しない場合は、新しいファイルを作成します。
Context.MODE_WORLD_READABLEおよびContext.MODE_WORLD_WRITEABLEは、他のアプリケーションがファイルの読み取りおよび書き込み権限を持っているかどうかを制御するために使用されます。
MODE_WORLD_READABLE:現在のファイルを他のアプリケーションで読み取ることができることを示します。MODE_WORLD_WRITEABLE:現在のファイルを他のアプリケーションで書き込むことができることを示します。
ファイルを他のアプリケーションで読み書きできるようにする場合は、次のものを渡すことができます
。openFileOutput( "itcast.txt"、Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);