如何缓存已解析的 JSON 以供离线使用
How to Cache Parsed JSON for Offline usage
我已经解析 JSON 成功,但现在我想缓存它以供离线使用,即使互联网不可用,如果有任何新条目出现我也想缓存它。
缓存数据的最佳选择是什么? SharedPreferences
或 SQLite database
这是我的代码,我用它来解析 JSON:
public class MainActivity extends Activity {
ArrayList<Actors> actorsList;
ActorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actorsList = new ArrayList<Actors>();
new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");
ListView listview = (ListView)findViewById(R.id.list);
adapter = new ActorAdapter(getApplicationContext(), R.layout.row, actorsList);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long id) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), actorsList.get(position).getName(), Toast.LENGTH_LONG).show();
}
});
}
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading, please wait");
dialog.setTitle("Connecting server");
dialog.show();
dialog.setCancelable(false);
}
@Override
protected Boolean doInBackground(String... urls) {
try {
//------------------>>
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Actors actor = new Actors();
actor.setName(object.getString("name"));
actor.setDescription(object.getString("description"));
actorsList.add(actor);
}
return true;
}
//------------------>>
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
}
And what would be the best option to cache data ? SharedPreferences or SQLite database
这完全基于您收到的数据。
- 如果数据很小,非结构化数据则使用Shared Pref。
- 如果数据很大,结构化数据则使用SQLite。
但为了更好地存储完整数据,您可以使用 file concept。将字符串数据存储在您的代码中 String data = EntityUtils.toString(entity);
data
您必须将来自服务器的数据的任何更改保存到 file.If 将其添加到 file.And 如果互联网,则检索数据不存在。从上面link.
得到文件操作的示例代码
为什么不使用类似这样的方法将其保存到应用程序的缓存文件夹中:
String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
path += "data";
File data = new File(path);
if (!data.createNewFile()) {
data.delete();
data.createNewFile();
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
objectOutputStream.writeObject(actorsList);
objectOutputStream.close();
之后,您可以随时阅读它:
List<?> list = null;
File data = new File(path);
try {
if(data.exists()) {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
list = (List<Object>) objectInputStream.readObject();
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
更新: 好的,将 class 命名为 ObjectToFileUtil,将此代码粘贴到创建的 class
package <yourpackagehere>;
import android.os.Environment;
import java.io.*;
public class ObjectToFileUtil {
public static String objectToFile(Object object) throws IOException {
String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
path += "data";
File data = new File(path);
if (!data.createNewFile()) {
data.delete();
data.createNewFile();
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
objectOutputStream.writeObject(object);
objectOutputStream.close();
return path;
}
public static Object objectFromFile(String path) throws IOException, ClassNotFoundException {
Object object = null;
File data = new File(path);
if(data.exists()) {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
object = objectInputStream.readObject();
objectInputStream.close();
}
return object;
}
}
将 < yourpackagehere > 更改为您的包名称,不要忘记添加 WRITE_EXTERNAL_STORAGE 权限 AndroidManifest.xml.在您的 MainActivity 添加字段
private String dataPath;
并将 JSONAsyncTask class 的 onPostExecute 方法替换为
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter.notifyDataSetChanged();
if(result) {
try {
dataPath = objectToFile(arrayList);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
现在您可以随时使用
从文件中获取演员列表
try {
actorsList = (ArrayList<Actors>)objectFromFile(dataPath);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
如果您想在关闭应用程序后保存文件路径,您必须保存 dataPath 字符串(并在应用程序启动时加载),例如,使用 SharedPreferences.
我已经解析 JSON 成功,但现在我想缓存它以供离线使用,即使互联网不可用,如果有任何新条目出现我也想缓存它。
缓存数据的最佳选择是什么? SharedPreferences
或 SQLite database
这是我的代码,我用它来解析 JSON:
public class MainActivity extends Activity {
ArrayList<Actors> actorsList;
ActorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actorsList = new ArrayList<Actors>();
new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");
ListView listview = (ListView)findViewById(R.id.list);
adapter = new ActorAdapter(getApplicationContext(), R.layout.row, actorsList);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long id) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), actorsList.get(position).getName(), Toast.LENGTH_LONG).show();
}
});
}
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading, please wait");
dialog.setTitle("Connecting server");
dialog.show();
dialog.setCancelable(false);
}
@Override
protected Boolean doInBackground(String... urls) {
try {
//------------------>>
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Actors actor = new Actors();
actor.setName(object.getString("name"));
actor.setDescription(object.getString("description"));
actorsList.add(actor);
}
return true;
}
//------------------>>
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
}
And what would be the best option to cache data ? SharedPreferences or SQLite database
这完全基于您收到的数据。
- 如果数据很小,非结构化数据则使用Shared Pref。
- 如果数据很大,结构化数据则使用SQLite。
但为了更好地存储完整数据,您可以使用 file concept。将字符串数据存储在您的代码中 String data = EntityUtils.toString(entity);
data
您必须将来自服务器的数据的任何更改保存到 file.If 将其添加到 file.And 如果互联网,则检索数据不存在。从上面link.
为什么不使用类似这样的方法将其保存到应用程序的缓存文件夹中:
String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
path += "data";
File data = new File(path);
if (!data.createNewFile()) {
data.delete();
data.createNewFile();
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
objectOutputStream.writeObject(actorsList);
objectOutputStream.close();
之后,您可以随时阅读它:
List<?> list = null;
File data = new File(path);
try {
if(data.exists()) {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
list = (List<Object>) objectInputStream.readObject();
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
更新: 好的,将 class 命名为 ObjectToFileUtil,将此代码粘贴到创建的 class
package <yourpackagehere>;
import android.os.Environment;
import java.io.*;
public class ObjectToFileUtil {
public static String objectToFile(Object object) throws IOException {
String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
path += "data";
File data = new File(path);
if (!data.createNewFile()) {
data.delete();
data.createNewFile();
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
objectOutputStream.writeObject(object);
objectOutputStream.close();
return path;
}
public static Object objectFromFile(String path) throws IOException, ClassNotFoundException {
Object object = null;
File data = new File(path);
if(data.exists()) {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
object = objectInputStream.readObject();
objectInputStream.close();
}
return object;
}
}
将 < yourpackagehere > 更改为您的包名称,不要忘记添加 WRITE_EXTERNAL_STORAGE 权限 AndroidManifest.xml.在您的 MainActivity 添加字段
private String dataPath;
并将 JSONAsyncTask class 的 onPostExecute 方法替换为
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter.notifyDataSetChanged();
if(result) {
try {
dataPath = objectToFile(arrayList);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
现在您可以随时使用
从文件中获取演员列表try {
actorsList = (ArrayList<Actors>)objectFromFile(dataPath);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
如果您想在关闭应用程序后保存文件路径,您必须保存 dataPath 字符串(并在应用程序启动时加载),例如,使用 SharedPreferences.