在对App进行数据加载的时候,会遇到没有网的情况,这个时候,我们会想对上一次加载的数据进行缓存,避免页面出现空白的情况,这种情况一般在加载成功之后,保存到本地,然后在下次加载错误的时候,展示上次的数据就行了,但是会有一个例外,就是当用户第一次下载app,当时并没有打开,在无网的情况下打开了app,这个时候,并没有缓存上一次加载成功的数据,也会出现页面数据大面积的空白的情况(一般公司没这个要求。。。然而我这xx公司)。
解决方式:将初始化数据放在assets目录下,在启动app,例如在闪屏页中复制到本地,然后在第一次打开app加载错误的时候,读取缓存的数据,在下次加载成功之后,使用上一次的数据,可以说该预埋数据只是在上述情况才会有用。看代码:
public class AssetCopyer {
private String asset_list_fileName;
private final Context mContext;
private final AssetManager mAssetManager;
private File mAppDirectory;
public AssetCopyer(Context context, String asset_list_fileName) {
mContext = context;
mAssetManager = context.getAssets();
this.asset_list_fileName = asset_list_fileName;
}
/**
* 将assets目录下指定的文件拷贝到sdcard中
* @return 是否拷贝成功,true 成功;false 失败
* @throws IOException
*/
public boolean copy() throws IOException {
List<String> srcFiles = new ArrayList<>();
//获取系统在SDCard中为app分配的目录,eg:/sdcard/Android/data/$(app's package)
//该目录存放app相关的各种文件(如cache,配置文件等),unstall app后该目录也会随之删除
mAppDirectory = mContext.getExternalFilesDir(null);
if (null == mAppDirectory) {
return false;
}
//读取assets/$(subDirectory)目录下的assets.lst文件,得到需要copy的文件列表
List<String> assets = getAssetsList();
for( String asset : assets ) {
//如果不存在,则添加到copy列表
if( ! new File(mAppDirectory,asset).exists() ) {
srcFiles.add(asset);
}
}
//依次拷贝到App的安装目录下
for( String file : srcFiles ) {
copy(file);
}
return true;
}
/**
* 获取需要拷贝的文件列表(记录在assets/assets.lst文件中)
* @return 文件列表
* @throws IOException
*/
protected List<String> getAssetsList() throws IOException {
List<String> files = new ArrayList<>();
InputStream listFile = mAssetManager.open(new File(asset_list_fileName).getPath());
BufferedReader br = new BufferedReader(new InputStreamReader(listFile));
String path;
while (null != (path = br.readLine())) {
files.add(path);
}
return files;
}
/**
* 执行拷贝任务
* @param asset 需要拷贝的assets文件路径
* @return 拷贝成功后的目标文件句柄
* @throws IOException
*/
protected File copy( String asset ) throws IOException {
InputStream source = mAssetManager.open(new File(asset).getPath());
File destinationFile = new File(mAppDirectory, asset);
if(destinationFile.exists()){
return destinationFile;
}
destinationFile.getParentFile().mkdirs();
OutputStream destination = new FileOutputStream(destinationFile);
byte[] buffer = new byte[1024];
int nread;
while ((nread = source.read(buffer)) != -1) {
if (nread == 0) {
nread = source.read();
if (nread < 0)
break;
destination.write(nread);
continue;
}
destination.write(buffer, 0, nread);
}
destination.close();
return destinationFile;
}
}
上面是一个拷贝到app目录下的工具类(/sdcard/Android/data/$(app's package)),拷贝原理是,先将assets目录下的需要拷贝的文件名字添加到一个.text文本文件中 eg:
assets.lst.txt
home_banner_01.png
shop_banner_01.png
shop_item_01.png
shop_item_02.png
shop_item_03.png
shop_item_04.png
shop_item_05.png
shop_item_06.png
shop_item_07.png
shop_item_08.png
shop_item_09.png
shop_label_01.png
shop_label_02.png
assets目录:
最后是两个json文件(缓存的策略是使用SharedPreferences 保存json数据,但是图片无法缓存,这个时候就需要将json中的url对应保存在本地的文件名字)。
贴一段json:image_url就是对应的app目录下的文件
{
"banner_list": [
{
"img": "\/sdcard\/Android\/data\/niubi\/files\/shop_banner_01.png"
}
],
"note_list": [],
"shop_list": [
{
"icon": "",
"title": "",
"goods_list_url": "https:\/\/niubi\/shop\/goods\/0\/category-list",
"category": [
{
"row": 1,
"col": 3,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_01.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/0\/category-list"
}
]
},
{
"icon": "\/sdcard\/Android\/data\/niubi\/files\/shop_label_01.png",
"title": "Apple",
"goods_list_url": "https:\/\/niubi\/shop\/goods\/91\/category-list",
"category": [
{
"row": 1,
"col": 1,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_02.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/1941"
},
{
"row": 1,
"col": 1,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_03.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/1931"
},
{
"row": 1,
"col": 1,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_04.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/1921"
},
{
"row": 1,
"col": 3,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_05.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/91\/category-list"
}
]
},
{
"icon": "\/sdcard\/Android\/data\/niubi\/files\/shop_label_02.png",
"title": "\u7f8e\u5986",
"goods_list_url": "https:\/\/niubi\/shop\/goods\/34\/category-list",
"category": [
{
"row": 1,
"col": 1,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_06.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/2161"
},
{
"row": 1,
"col": 1,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_07.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/2171"
},
{
"row": 1,
"col": 1,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_08.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/2191"
},
{
"row": 1,
"col": 3,
"image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_09.png",
"category_goods_list": "https:\/\/niubi\/shop\/goods\/34\/category-list"
}
]
}
]
}
再看下加载的具体使用步骤:
1.在闪屏页中 : 复制assets目录下的文件
new Thread(new Runnable() {
@Override
public void run() {
AssetCopyer assetCopyer = new AssetCopyer(SplashActivity.this,"assets.lst");
try {
assetCopyer.copy();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
2.加载数据:
HttpKit.me().post(params, new JSONCallback<HomePageNew>() {
@Override
public void onError(ApiException e) {
super.onError(e);
loadErrorData();
}
@Override
public void onResponse(HomePageNew response) {
(sharedPreferences工具类)
StorageManager.getInstance().insert("homepage", mHomePageNew);//保存json数据到本地
...........更新页面操作
...........
}
});
//加载错误的时候页面展示
private void loadErrorData() {
if (mHomePageNew != null) {
return;
}
mHomePageNew = StorageManager.getInstance().query("homepage", HomePageNew.class);
if (mHomePageNew != null) {//如果获取保存在本地的数据不为null,就使用保存在本地的数据
。。。。。。。。。。。。
} else {//第一次打开app无缓存并且无网的情况下,设置一个默认的数据 读取json数据,展示
String jsonString = null;
try {
InputStream home_json_txt = AppKit.me.getAssets().open("rwh_home_data.json");
int available = home_json_txt.available();
byte[] bytes = new byte[available];
home_json_txt.read(bytes);
home_json_txt.close();
jsonString = new String(bytes).trim();
} catch (IOException e1) {
e1.printStackTrace();
}
if (jsonString != null) {
HomePageNew homePageNew = GsonKit.fromJson(jsonString, HomePageNew.class);
if (homePageNew != null) {
。。。。。。。。。。。//更新页面操作
}
}
}
}
上面就基本完成了所要的需求。