解析Json数据并缓存图片到sdcard

需求:

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;
	}

}
运行结果:

解析Json数据并缓存图片到sdcard_第1张图片

另外,下面是我们打印的Log日志的截图,说明图片是从本地读取的:

解析Json数据并缓存图片到sdcard_第2张图片


你可能感兴趣的:(Android开发)