黑马北京新闻项目连载(8)--->画片缓存

先看主页的布局文件menu_photo_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/lv_photo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="#fff"
        android:divider="@null" />

</FrameLayout>

看每个Item的布局文件list_photo_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="@drawable/pic_list_item_bg"
        android:gravity="center"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/iv_pic"
            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:scaleType="centerCrop"
            android:src="@drawable/news_pic_default" />

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="标题"
            android:singleLine="true"
            android:textColor="#000"
            android:textSize="22sp" />
    </LinearLayout>

</LinearLayout>

PhotosData

package com.example.custombitmaputils;

import java.util.ArrayList;

/**
 * 组图数据
 */
public class PhotosData {

	public int retcode;
	public PhotosInfo data;

	public class PhotosInfo {
		public String title;
		public ArrayList<PhotoInfo> news;
	}

	public class PhotoInfo {
		public String id;
		public String listimage;
		public String pubdate;
		public String title;
		public String type;
		public String url;
	}
}

PrefUtils

package com.example.custombitmaputils;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * SharePreference封装
 * 
 */
public class PrefUtils {

	public static final String PREF_NAME = "config";

	public static boolean getBoolean(Context ctx, String key,
			boolean defaultValue) {
		SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
				Context.MODE_PRIVATE);
		return sp.getBoolean(key, defaultValue);
	}

	public static void setBoolean(Context ctx, String key, boolean value) {
		SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
				Context.MODE_PRIVATE);
		sp.edit().putBoolean(key, value).commit();
	}

	public static String getString(Context ctx, String key, String defaultValue) {
		SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
				Context.MODE_PRIVATE);
		return sp.getString(key, defaultValue);
	}

	public static void setString(Context ctx, String key, String value) {
		SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
				Context.MODE_PRIVATE);
		sp.edit().putString(key, value).commit();
	}
}

MD5Encoder

package com.example.custombitmaputils;

import java.security.MessageDigest;

public class MD5Encoder {

	public static String encode(String string) throws Exception {
		byte[] hash = MessageDigest.getInstance("MD5").digest(
				string.getBytes("UTF-8"));
		StringBuilder hex = new StringBuilder(hash.length * 2);
		for (byte b : hash) {
			if ((b & 0xFF) < 0x10) {
				hex.append("0");
			}
			hex.append(Integer.toHexString(b & 0xFF));
		}
		return hex.toString();
	}
}

CacheUtils

package com.example.custombitmaputils;

import android.content.Context;

/**
 * 缓存工具类
 */
public class CacheUtils {

	/**
	 * 设置缓存 key 是url, value是json
	 */
	public static void setCache(String key, String value, Context ctx) {
		PrefUtils.setString(ctx, key, value);
		//可以将缓存放在文件中, 文件名就是Md5(url), 文件内容是json
	}

	/**
	 * 获取缓存 key 是url
	 */
	public static String getCache(String key, Context ctx) {
		return PrefUtils.getString(ctx, key, null);
	}
}

MainActivity

package com.example.custombitmaputils;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.custombitmaputils.PhotosData.PhotoInfo;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;

public class MainActivity extends Activity {
	public static final String SERVER_URL = "http://10.0.2.2:8080/zhbj";
	public static final String PHOTOS_URL = SERVER_URL
			+ "/photos/photos_1.json";

	private ListView lv_photo;
	private ArrayList<PhotoInfo> mPhotoList;
	private PhotoAdapter mAdapter;
	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.menu_photo_pager);
		// 控件
		lv_photo = (ListView) findViewById(R.id.lv_photo);
		// 数据
		getDataFromServer();
		// 适配器

		// 设置适配器
	}

	private void getDataFromServer() {
		HttpUtils utils = new HttpUtils();
		utils.send(HttpMethod.GET, PHOTOS_URL, new RequestCallBack<String>() {

			@Override
			public void onSuccess(ResponseInfo<String> responseInfo) {
				String result = (String) responseInfo.result;
				parseData(result);
				// 设置缓存
				CacheUtils.setCache(PHOTOS_URL, result,
						MainActivity.this);
			}

			@Override
			public void onFailure(HttpException error, String msg) {
				error.printStackTrace();
			}
		});
	}

	protected void parseData(String result) {

		Gson gson = new Gson();
		PhotosData data = gson.fromJson(result, PhotosData.class);

		mPhotoList = data.data.news;// 获取组图列表集合

		if (mPhotoList != null) {
			mAdapter = new PhotoAdapter();
			lv_photo.setAdapter(mAdapter);
		}

	}
	
	

	class PhotoAdapter extends BaseAdapter {

		private MyBitmapUtils utils;

		public PhotoAdapter() {
			utils = new MyBitmapUtils();
		}

		@Override
		public int getCount() {
			return mPhotoList.size();
		}

		@Override
		public PhotoInfo getItem(int position) {
			return mPhotoList.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				convertView = View.inflate(MainActivity.this, R.layout.list_photo_item,
						null);

				holder = new ViewHolder();
				holder.tvTitle = (TextView) convertView
						.findViewById(R.id.tv_title);
				holder.ivPic = (ImageView) convertView
						.findViewById(R.id.iv_pic);

				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			PhotoInfo item = getItem(position);

			holder.tvTitle.setText(item.title);

			utils.display(holder.ivPic, item.listimage);

			return convertView;
		}

	}
	static class ViewHolder {
		public TextView tvTitle;
		public ImageView ivPic;
	}

}

————————————以下是三级缓存代码——————————

MyBitmapUtils

package com.example.custombitmaputils;

import android.graphics.Bitmap;
import android.widget.ImageView;


/**
 * 自定义图片加载工具
 */
public class MyBitmapUtils {

	NetCacheUtils mNetCacheUtils;
	LocalCacheUtils mLocalCacheUtils;
	MemoryCacheUtils mMemoryCacheUtils;

	public MyBitmapUtils() {
		mMemoryCacheUtils = new MemoryCacheUtils();
		mLocalCacheUtils = new LocalCacheUtils();
		mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, mMemoryCacheUtils);
	}

	public void display(ImageView ivPic, String url) {
		ivPic.setImageResource(R.drawable.news_pic_default);// 设置默认加载图片

		Bitmap bitmap = null;
		// 从内存读
		bitmap = mMemoryCacheUtils.getBitmapFromMemory(url);
		if (bitmap != null) {
			ivPic.setImageBitmap(bitmap);
			System.out.println("从内存读取图片啦...");
			return;
		}

		// 从本地读
		bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
		if (bitmap != null) {
			ivPic.setImageBitmap(bitmap);
			System.out.println("从本地读取图片啦...");
			mMemoryCacheUtils.setBitmapToMemory(url, bitmap);// 将图片保存在内存
			return;
		}

		// 从网络读
		mNetCacheUtils.getBitmapFromNet(ivPic, url);
	}

}


MemoryCacheUtils

package com.example.custombitmaputils;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

/**
 * 内存缓存
 */
public class MemoryCacheUtils {

	// private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
	// HashMap<String, SoftReference<Bitmap>>();
	private LruCache<String, Bitmap> mMemoryCache;

	public MemoryCacheUtils() {
		//设置缓存的大小
		long maxMemory = Runtime.getRuntime().maxMemory() / 8;
		mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
			// 获取图片占用内存大小
			@Override
			protected int sizeOf(String key, Bitmap value) {
				int byteCount = value.getRowBytes() * value.getHeight();
				return byteCount;
			}
		};
	}

	/**
	 * 从内存读
	 * 
	 * @param url
	 */
	public Bitmap getBitmapFromMemory(String url) {
		// SoftReference<Bitmap> softReference = mMemoryCache.get(url);
		// if (softReference != null) {
		// Bitmap bitmap = softReference.get();
		// return bitmap;
		// }
		return mMemoryCache.get(url);
	}

	/**
	 * 写内存
	 * 
	 * @param url
	 * @param bitmap
	 */
	public void setBitmapToMemory(String url, Bitmap bitmap) {
		// SoftReference<Bitmap> softReference = new
		// SoftReference<Bitmap>(bitmap);
		// mMemoryCache.put(url, softReference);
		mMemoryCache.put(url, bitmap);
	}
}

LocalCacheUtils

package com.example.custombitmaputils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;


import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;

/**
 * 本地缓存
 */
public class LocalCacheUtils {

	public static final String CACHE_PATH = Environment
			.getExternalStorageDirectory().getAbsolutePath() + "/zhbj_cache_52";

	/**
	 * 从本地sdcard读图片
	 */
	public Bitmap getBitmapFromLocal(String url) {
		try {
			String fileName = MD5Encoder.encode(url);
			File file = new File(CACHE_PATH, fileName);

			if (file.exists()) {
				Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
						file));
				return bitmap;
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 向sdcard写图片
	 * 
	 * @param url
	 * @param bitmap
	 */
	public void setBitmapToLocal(String url, Bitmap bitmap) {
		try {
			String fileName = MD5Encoder.encode(url);

			File file = new File(CACHE_PATH, fileName);

			File parentFile = file.getParentFile();
			if (!parentFile.exists()) {// 如果文件夹不存在, 创建文件夹
				parentFile.mkdirs();
			}

			// 将图片保存在本地
			bitmap.compress(CompressFormat.JPEG, 100,
					new FileOutputStream(file));
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}


NetCacheUtils

package com.example.custombitmaputils;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

/**
 * 网络缓存
 */
public class NetCacheUtils {

	private LocalCacheUtils mLocalCacheUtils;
	private MemoryCacheUtils mMemoryCacheUtils;

	public NetCacheUtils(LocalCacheUtils localCacheUtils,
			MemoryCacheUtils memoryCacheUtils) {
		mLocalCacheUtils = localCacheUtils;
		mMemoryCacheUtils = memoryCacheUtils;
	}

	/**
	 * 从网络下载图片
	 * 参数:imageView控件、控件对应的图片Url地址路径
	 */
	public void getBitmapFromNet(ImageView ivPic, String url) {
		// 启动AsyncTask,
		new BitmapTask().execute(ivPic, url);
	}

	/**
	 * Handler和线程池的封装
	 * 
	 * 第一个泛型: 参数类型 第二个泛型: 更新进度的泛型, 第三个泛型是onPostExecute的返回结果
	 */
	class BitmapTask extends AsyncTask<Object, Void, Bitmap> {

		private ImageView ivPic;
		private String url;

		/**
		 * 后台耗时方法在此执行, 子线程
		 */
		@Override
		protected Bitmap doInBackground(Object... params) {
			ivPic = (ImageView) params[0];
			url = (String) params[1];

			// 将url和imageview绑定
			ivPic.setTag(url);

			return downloadBitmap(url);
		}

		/**
		 * 更新进度, 主线程
		 */
		@Override
		protected void onProgressUpdate(Void... values) {
			super.onProgressUpdate(values);
		}

		/**
		 * 耗时方法结束后,执行该方法, 主线程
		 */
		@Override
		protected void onPostExecute(Bitmap result) {
			if (result != null) {
				String bindUrl = (String) ivPic.getTag();

				if (url.equals(bindUrl)) {// 确保图片设定给了正确的imageview
					ivPic.setImageBitmap(result);
					mLocalCacheUtils.setBitmapToLocal(url, result);// 将图片保存在本地
					mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图片保存在内存
					System.out.println("从网络缓存读取图片啦...");
				}
			}
		}
	}

	/**
	 * 下载图片
	 */
	private Bitmap downloadBitmap(String url) {

		HttpURLConnection conn = null;
		try {
			conn = (HttpURLConnection) new URL(url).openConnection();

			conn.setConnectTimeout(5000);
			conn.setReadTimeout(5000);
			conn.setRequestMethod("GET");
			conn.connect();

			int responseCode = conn.getResponseCode();
			if (responseCode == 200) {
				/**
				 * 获取图片输入流
				 */
				InputStream inputStream = conn.getInputStream();
				
				//图片压缩处理
				BitmapFactory.Options option = new BitmapFactory.Options();
				option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
				option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式
				
				/**
				 * 将图片输入流转为图片
				 */
				Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);
				return bitmap;
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			conn.disconnect();
		}

		return null;
	}

}


你可能感兴趣的:(黑马北京新闻项目连载(8)--->画片缓存)