Android图片加载问题
图片处理一直是Android程序员需要注意的地方,在移动设备上内存资源有限的条件下,图片的加载很容易出现个OOM异常和应用的流畅性问题。
现在也有很流行的开源框架实现了图片的异步加载和二级缓存的机制,不能重复造轮子,但是为了造更好的轮子我们应该知道轮子是怎么制造的。
先看代码
核心类:ImageLoader
package com.example.zfy.imageloader.ImageLoader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by zfy on 2016/7/21.
*/
public class ImageLoader {
//设置缓存
//软引用避免OOM异常
public Map<String ,SoftReference<Drawable>> imageCache = new HashMap<String,SoftReference<Drawable>>();
//线程池管理图片异步加载的线程
private ExecutorService executorService = Executors.newFixedThreadPool(5);
private Handler mHandler = new Handler();
//模拟网络延迟用的标记,请忽略
private boolean isFirst = true;
//加载图片的主要方法
public Drawable loadDrawable(final String imageUrl, final ImageCallback callback){
Drawable image = null;
//缓存中有,直接取出使用
if(imageCache.containsKey(imageUrl)){
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
if(softReference.get() != null){
image = softReference.get();
return image;
}
}
executorService.submit(new Runnable() {
@Override
public void run() {
//开启线程从URL中获取图片
final Drawable drawable = loadDrawableFromUrl(imageUrl);
imageCache.put(imageUrl,new SoftReference<Drawable>(drawable));
mHandler.post(new Runnable() {
@Override
public void run() {
//执行回调函数 callback.imageLoaded(imageUrl,drawable);
}
});
}
});
return null;
}
//加载网络图片
private Drawable loadDrawableFromUrl(String imageUrl) {
if(isFirst){
isFirst = false;
SystemClock.sleep(12000);
}
SystemClock.sleep(2000);
try {
return Drawable.createFromStream(new URL(imageUrl).openStream(),"image.png");
} catch (IOException e) {
e.printStackTrace();
Log.d("出现异常","TAG");
throw new RuntimeException(e);
}
}
//定义接口执行外部的回调函数
public interface ImageCallback {
public void imageLoaded(String Url,Drawable imageDrawable);
}
}
外部调用:
package com.example.zfy.imageloader;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.example.zfy.imageloader.Adapter.ListViewAdapter;
import com.example.zfy.imageloader.ImageLoader.ImageLoader;
import com.example.zfy.imageloader.ItemInfo.Image;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class MainActivity extends AppCompatActivity implements ImageLoader.ImageCallback{
private ListView mListView;
private ImageView mImageView;
private TextView mTextView;
private Vector<Image> mImsges= new Vector<>();
private ImageLoader mImageLoader;
private ListViewAdapter mAdapter;
private String[] mUrls = new String[]{
"http://www.baidu.com/img/baidu_logo.gif",
"http://www.chinatelecom.com.cn/images/logo_new.gif",
"http://cache.soso.com/30d/img/web/logo.gif",
"http://csdnimg.cn/www/images/csdnindex_logo.gif",
"http://images.cnblogs.com/logo_small.gif"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
loadImage(mUrls);
}
private void init() {
mImageLoader = new ImageLoader();
mListView = (ListView) findViewById(R.id.id_lv);
mImageView = (ImageView) findViewById(R.id.id_iv);
mTextView = (TextView) findViewById(R.id.id_tv);
//设置默认图片
Resources res = this.getResources();
mImsges.add(new Image(res.getDrawable(R.drawable.close),"http://www.baidu.com/img/baidu_logo.gif"));
mImsges.add(new Image(res.getDrawable(R.drawable.close),"http://www.chinatelecom.com.cn/images/logo_new.gif"));
mImsges.add(new Image(res.getDrawable(R.drawable.close),"http://cache.soso.com/30d/img/web/logo.gif"));
mImsges.add(new Image(res.getDrawable(R.drawable.close),"http://csdnimg.cn/www/images/csdnindex_logo.gif"));
mImsges.add(new Image(res.getDrawable(R.drawable.close),"http://images.cnblogs.com/logo_small.gif"));
mAdapter = new ListViewAdapter(mImsges,this);
mListView.setAdapter(mAdapter);
}
//加载图片
//内存中有的先加载上去
//没有的在回调函数中获得
private void loadImage(String[] mUrls) {
Vector<Image> temp = new Vector<>();
for(String url : mUrls) {
Drawable myimage = mImageLoader.loadDrawable(url,this);
if(myimage != null){
for(Image image : mImsges){
String str = image.getImageUrl();
if(str.equals(url) ){
image.setImage(myimage);
}
temp.add(image);
}
mImsges = temp;
mAdapter.notifyDataSetChanged();
//notifyDataChange
}
}
}
//回调函数
@Override
public void imageLoaded(String Url,Drawable imageDrawable) {
Vector<Image> temp = new Vector<>();
for(Image image : mImsges){
String str = image.getImageUrl();
if(str.equals(Url) ){
image.setImage(imageDrawable);
}
temp.add(image);
}
mImsges = temp;
mAdapter.notifyDataSetChanged();
//notifyDataChange
}
}