<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
activity_main.xml
<Button
android:onClick="displayImage"
android:text="加载图片"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
ImageHelper
//复制就行
public class ImageHelper {
private static ImageHelper imageHelper = null;
private final LruCache<String, Bitmap> lruCache;
public static ImageHelper getInstance() {
if (imageHelper == null) {
synchronized (ImageHelper.class) {
if (imageHelper == null) {
imageHelper = new ImageHelper();
}
}
}
return imageHelper;
}
private ImageHelper() {
//初始化内存中存图片需要的lruCache
//创建对象的时候就去分配一个内存
//使用LruCache对象进行内存的缓存...底层是LinedHashMap..特点:当内存不够用的时候,可以自动移除最近使用次数最少的对象
//初始化的时候需要指定该缓存的对象能够存储多大的空间...最大内存的1/8....例如:4M
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
//计算每一张图片 所占空间的大小....lruCache会根据存储的对象的大小跟maxSize进行对比,如果继续再存储一张会超过maxSize,将会使用lru算法删除缓存对象
lruCache = new LruCache<String, Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
//计算每一张图片 所占空间的大小....lruCache会根据存储的对象的大小跟maxSize进行对比,如果继续再存储一张会超过maxSize,将会使用lru算法删除缓存对象
return value.getRowBytes()*value.getHeight();
}
};
}
public void displayImage(String url, ImageView imageView) {
//1.先根据url获取内存中的图片 有,显示图片,结束当前方法的执行
Bitmap bitmap = lruCache.get(url);
if (bitmap != null) {
Log.e("----","---内存中获取");
imageView.setImageBitmap(bitmap);
return;
}
//2.内存中没有,,,取sd卡中的图片 有,添加到内存,显示图片,,,结束方法向下执行
bitmap = loadFromLocal(url);
if (bitmap != null) {
Log.e("-----","----sd卡获取");
imageView.setImageBitmap(bitmap);
return;
}
//3.sd卡里面也没有,,,,网络上获取图片,保存到内存,sd卡中,,显示图片
loadFromNet(url,imageView);
}
/**
* 网络上获取
* @param path
* @param imageView
*/
private void loadFromNet(final String path, final ImageView imageView) {
Log.e("-----","---网络获取");
//网络上获取图片,
AsyncTask<Void, Void, Bitmap> asyncTask = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... voids) {
//获取网络数据
try {
URL url = new URL(path);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setReadTimeout(5000);
if (httpURLConnection.getResponseCode() == 200) {
InputStream inputStream = httpURLConnection.getInputStream();
//把这个字节流转成bitmap
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
// 保存到内存
lruCache.put(path,bitmap);
// 写入sd卡中
wrtieToSdCard(path,bitmap);
// 显示图片
imageView.setImageBitmap(bitmap);
}
};
asyncTask.execute();
}
/**
* 将图片写入sd卡
* @param url http://
* @param bitmap
*/
private void wrtieToSdCard(String url, Bitmap bitmap) {
try {
//使用url路径作为保存在sd卡上bitmap的文件名 但是url路径里面有特殊字符 需要编码一下
String path = encodeUrl(url);
File file = new File(getCacheDir(), path);
FileOutputStream fileOutputStream = new FileOutputStream(file);
//把bitmap图片压缩的输出流中,然后存到文件,,,JPEG以图片的格式,,100表示压缩率为0,,,70表示压缩率是30%
bitmap.compress(Bitmap.CompressFormat.JPEG,100,fileOutputStream);
fileOutputStream.close();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取把bitmap存在sd卡中的路径
* @return
*/
private File getCacheDir() {
File dir = null;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
dir = new File(Environment.getExternalStorageDirectory(),"/CustomCache/pic");
if (! dir.exists()) {
dir.mkdirs();
}
}
return dir;
}
private String encodeUrl(String url) throws NoSuchAlgorithmException, UnsupportedEncodingException {
byte[] hash = MessageDigest.getInstance("MD5").digest(url.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();
}
/**
* 本地加载图片...取出sd卡的图片之后 写到内存
* @param url
* @return
*/
private Bitmap loadFromLocal(String url) {
try {
String path = encodeUrl(url);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File file = new File(getCacheDir(), path);
//把file转成bitmap
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
//写入内存
if (bitmap != null) {
lruCache.put(url,bitmap);
}
return bitmap;
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
MainActivity
//全局变量
private ImageView imageView;
imageView = findViewById(R.id.image_view);
//按钮点击事件
public void displayImage(View view) {
ImageHelper.getInstance().displayImage("http://img5.imgtn.bdimg.com/it/u=937840224,4190645943&fm=27&gp=0.jpg",imageView);
}