参考链接
https://blog.csdn.net/nzfxx/article/details/51818183
图片的工具类
public class MyImageTool {
private static MyImageTool myImageTool = new MyImageTool();
//改用缓存集合
private static LruCache mMCeche;
private MyImageTool() {
//这个是定义大小
//int maxSize = 1024*1024*4;
//注意这个地方及其的容易出错,因为我写成了freeMemory()/4+0.5f,导致大半天都集合都无法存入东西,因为两者不一样大了,而用int maxSize = 1024*1024*4;里面出现效果
int maxSize = (int) (Runtime.getRuntime().totalMemory());//四舍五入,用总内存就没错
mMCeche = new LruCache(maxSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
//这个是对应上面的byte,注意单位对应,如果这里想作为M那么上面就写4,这里就写/1024/1024
return value.getByteCount();
}
};
}
//1.上下文
static Context mContext;
public static MyImageTool with(Context context) {
mContext = context;
return myImageTool;
}
//2.路径
public RequestCreator load(String path) {
RequestCreator creator = new RequestCreator(path);
return creator;
}
Handler mHandler = new Handler();
public class RequestCreator {
String mUrl = null;
ImageView mIv;
RequestCreator(String path) {
mUrl = path;
}
//3.控件
public void into(ImageView iv) {
mIv = iv;
load();
}
private void load() {
/*-从内存里读取图片 HashMap-*/
if (loadFromCache()) return;
/*--从磁盘读取"文件"存入磁盘的是文件file-MD5统一名字,在内存中才是图片bitmap-用url当做名字就行,所以从磁盘读取需要转换成图片;--*/
if (loadFromDisk()) return;
/*--从网络获取,开启线程,然后子线程显示即可,再存磁盘,存内存--*/
loadFromNet();
}
//从内存读取
private boolean loadFromCache() {
Bitmap bitmapCeche = mMCeche.get(mUrl);
if (bitmapCeche != null) {
Log.d("RequestCreator", "显示的是内存的图");
mIv.setImageBitmap(bitmapCeche);
return true;
}
return false;
}
//从磁盘获取
private boolean loadFromDisk() {
File file = getFileName();
try {
if (file.exists()) {
Bitmap bitmapDisk = BitmapFactory.decodeStream(new FileInputStream(file));
if (bitmapDisk != null) {
Log.d("RequestCreator", "显示的是磁盘的图");
mIv.setImageBitmap(bitmapDisk);
//立马且存到内存
saveCeche(bitmapDisk);
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
//从网络获取,并存如磁盘和内存
private void loadFromNet() {
new Thread(new Runnable() {
@Override
public void run() {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(mUrl).openConnection();
conn.setConnectTimeout(4 * 1000);
conn.setReadTimeout(4 * 1000);
InputStream is = conn.getInputStream();
final Bitmap bitmap = BitmapFactory.decodeStream(is);
if (bitmap == null) {
//没有就显示错误图片
showErrorPic();
return;
}
//子线程->主线程显示
mHandler.post(new Runnable() {
@Override
public void run() {
Log.d("RequestCreator", "显示的是网络的图");
mIv.setImageBitmap(bitmap);
}
});
//存到磁盘是file格式,所以内部要处理
saveDisk(bitmap);
//存到内存的是纯bitmap格式.
saveCeche(bitmap);
conn.disconnect();
is.close();
} catch (IOException e) {
//异常显示错误图片
showErrorPic();
e.printStackTrace();
}
}
}).start();
}
//磁盘里的file文件名字
@NonNull
private File getFileName() {
String packageName = mContext.getPackageName();
File dir = new File("data/data/" + packageName + "/" + "myimage/");//自定义的
if (!dir.exists()) {
dir.mkdir();//没有就创建
}
String name = MD5Util.getMD5Str(mUrl);
return new File(dir, name);
}
//图片存到磁盘
private void saveDisk(Bitmap bitmap) {
File fileName = getFileName();
//bitmap->file,图片转成文件
try {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//图片存到内存的方法
private void saveCeche(Bitmap bitmap) {
mMCeche.put(mUrl, bitmap);
System.out.println("putSize---------------------------------------" + mMCeche.size());
}
//显示错误图片
private void showErrorPic() {
mHandler.post(new Runnable() {
@Override
public void run() {
Bitmap error = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher);
Toast.makeText(mContext, "Error", Toast.LENGTH_SHORT).show();
mIv.setImageBitmap(error);
}
});
}
}
}
activity中的代码
public class MainActivity extends AppCompatActivity {
ImageView img;
String imgURl = "http://cdn.lizhi.fm/radio_cover/2014/08/01/13399312812359682.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.img);
//使用框架
// Picasso.with(MainActivity.this).load(imgURl).into(mIv);
// UseTimeTool.getInstance().start();
//我们自己做的: 上下文->路径->控件
MyImageTool.with(MainActivity.this).load(imgURl).into(img);
// UseTimeTool.getInstance().stop();
}
}
MD5工具类
public class MD5Util {
public final static String getMD5Str(String pwd) {
//用于加密的字符
char md5String[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};
try {
//使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte数组中
byte[] btInput = pwd.getBytes();
//信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。
MessageDigest mdInst = MessageDigest.getInstance("MD5");
//MessageDigest对象通过使用 update方法处理数据, 使用指定的byte数组更新摘要
mdInst.update(btInput);
// 摘要更新之后,通过调用digest()执行哈希计算,获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) { // i = 0
byte byte0 = md[i]; //95
str[k++] = md5String[byte0 >>> 4 & 0xf]; // 5
str[k++] = md5String[byte0 & 0xf]; // F
}
//返回经过加密后的字符串
return new String(str);
} catch (Exception e) {
return null;
}
}
}