需求:
1、解析Json数据并按照指定的控件格式显示在Activity中。
2、把解析出来的图片缓存到sdcard,再次加载时,判断sdcard中是否有该文件,有的话就直接读取本地文件,否则就从网络下载。
3、对于图片的缓存应用非常广泛,这样在我们进行条目的加载时就可以直接从本地读取图片资源,免去了从网络加载图片的耗时操作
并且避免了加载图片时不同条目之间图片的错位。
对了,一提到对于sdcard的操作,一定要加上读写权限,今天因为没加权限纠结了半天代码,所以以后必须记住了。
好了,我们直接看代码吧,其中加注释的大部分是我们今天所学的内容,有一些没有加的都是之前学过的。
这是一个Fragment中的代码,在其中实现的相应功能。
package com.example.test_03_Two;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.spec.IvParameterSpec;
import com.example.test_03.R;
import com.example.test_03_bean.Data;
import com.example.test_03_bean.Feeds;
import com.example.test_03_bean.Result;
import com.example.test_03_http.HttpUtils;
import android.annotation.SuppressLint;
import android.app.ListFragment;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@SuppressLint({ "NewApi", "ValidFragment" })
public class RightFragment extends ListFragment {
//创建handler对象处理子线程发来的消息
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
holder.ivCover.setImageBitmap((Bitmap) msg.obj);
break;
case 2:
Toast.makeText(getActivity(), "下载图片出错!", 0).show();
break;
default:
break;
}
}
};
private ViewHolder holder;
private int id;
private String[] PATH = new String[]{
"http://litchiapi.jstv.com/api/GetFeeds?column=4&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41",
"http://litchiapi.jstv.com/api/GetFeeds?column=5&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41",
"http://litchiapi.jstv.com/api/GetFeeds?column=6&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41",
"http://litchiapi.jstv.com/api/GetFeeds?column=7&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41",
"http://litchiapi.jstv.com/api/GetFeeds?column=8&PageSize=20&pageIndex=1&val=100511D3BE5301280E0992C73A9DEC41"
};
private Result result;
private Data data;
private Listdatas;
private MyTask task;
private Feeds[] feeds;
private MyAdapter adapter;
private MyOpenHelper helper;
private SQLiteDatabase db;
private ContentValues values;
@SuppressLint("ValidFragment")
public RightFragment(int id) {
this.id = id;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
datas = new ArrayList();
helper = new MyOpenHelper(getActivity(), "news" + id + ".db",id);
db = helper.getWritableDatabase();
values = new ContentValues();
task = new MyTask();
task.execute(PATH[id]);
}
//获取填充对象的集合的异步任务
class MyTask extends AsyncTask>{
@Override
protected List doInBackground(String... params) {
String json = HttpUtils.getJsonContent(params[0]);
result = Result.getResult(json);
feeds = result.getParamz().getFeeds();
for (int i = 0; i < feeds.length; i++) {
data = feeds[i].getData();
values.put("subject", data.getSubject());
values.put("summary", data.getSummary());
values.put("changed", data.getChanged());
db.insert("news_0" + id, null, values);
values.clear();
datas.add(data);
}
return datas;
}
@Override
protected void onPostExecute(List result) {
super.onPostExecute(result);
adapter = new MyAdapter();
setListAdapter(adapter);
}
}
//自定义适配器
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
holder = new ViewHolder();
convertView = LayoutInflater.from(getActivity()).inflate(R.layout.right_layout, null);
holder.ivCover = (ImageView) convertView.findViewById(R.id.iv_cover);
holder.tvChanged = (TextView) convertView.findViewById(R.id.tv_changed);
holder.tvSubject = (TextView) convertView.findViewById(R.id.tv_subject);
holder.tvSummary = (TextView) convertView.findViewById(R.id.tv_summary);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
data = datas.get(position);
holder.tvChanged.setText(data.getChanged());
holder.tvSubject.setText(data.getSubject());
holder.tvSummary.setText(data.getSummary());
final String coverPath = data.getCover();
//获取图片的路径,这里因为解析数据中的路径不全,所以加上了"http://litchiapi.jstv.com"
//不过对于一般的解析数据都是有全路径的,所以视情况而定吧
final String path = "http://litchiapi.jstv.com" + coverPath;
//判断sdcard是否挂载
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//获取sdcard的路径
File sdcardFile = Environment.getExternalStorageDirectory();
//获取写入sdcard的文件的路径
final File file = new File(sdcardFile,getFileName(path));
//如果文件存在,就直接从文件中读取图片并显示
if(file.exists()){
Log.i("main", "本地读取");
//通过文件路径设置Bitmap图片
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
holder.ivCover.setImageBitmap(bitmap);
}
//如果文件不存在,就新建一个子线程把图片下载到本地并显示出来
else {
Thread thread = new Thread() {
@Override
public void run() {
try {
Log.i("main", "从网络下载的图片");
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
InputStream is = conn.getInputStream();
//获取文件写入流把is中的图片信息写入sdcard
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
//通过文件名来设置Bitmap图像
Bitmap bitmap = BitmapFactory.decodeFile(file
.getAbsolutePath());
//向主线程发送消息
Message message = handler.obtainMessage();
message.obj = bitmap;
message.what = 1;
handler.sendMessage(message);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
//这里一定不要忘了开启线程,不然会报异常
thread.start();
}
}else{
Message message = handler.obtainMessage();
message.what = 2;
handler.sendMessage(message);
}
return convertView;
}
//实现获得文件路径中文件名的工具函数
public String getFileName(String path){
int index = path.lastIndexOf("/");
return path.substring(index + 1);
}
}
class ViewHolder{
private TextView tvSubject,tvSummary,tvChanged;
private ImageView ivCover;
}
}
运行结果:
另外,下面是我们打印的Log日志的截图,说明图片是从本地读取的: