先看主页的布局文件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>
<?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>
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; } }
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(); } }
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(); } }
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); } }
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); } }
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); } }
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(); } } }
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; } }