您的位置:首页 > 移动开发 > Android开发

Android ListView,GridView,RecyclerView图片加载错位闪动问题解决办法

2016-04-12 13:43 921 查看
最近看了一下RecyclerView这个控件,的确非常好用,但是也并没有摆脱这种问题,recyclerview内部好像自带有控件的复用。

问题的根源还是控件的复用以及异步加载所引起的问题

解决思路:

1.使用缓存,从缓存中加载的速度大大少于从网络加载

2.设置默认图片,当一个item设置个图片然后被复用,而当前显示的图片还没有数据,正在从网络获取,这个时候此item就会显示复用前显示的图片,而当前应该显示的图片从网络中获取到之后就会重新加载上去就出现的图片闪动的情况

3.给ImageView设置TAG

我封装了一个类来进行网络获取加载图片,代码比较简单,用起来也非常方便,诸位可以根据自己的需求进行修改

话不多说上代码:

package My.Utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.util.LruCache;
import android.widget.ImageView;

import com.wkk.myutils.R;

import java.io.IOException;

/**
*
4000
Created by Think on 2016/4/11.
*/
public class ImageLoader {

private static My.Utils.ImageLoader ImageLoader;
private LruCache<String, Bitmap> lruCache;
public static final int ID = -100;
private boolean Savedlocal = false;//此属性控制是否需要缓存到本地
private Context context;

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
private ImageLoader(Context context) {
this.context = context;
// 版本低于12 数量 大于等于12 容量
if (Build.VERSION.SDK_INT < 12) {
lruCache = new LruCache<String, Bitmap>(100);
} else {
lruCache = new LruCache<String, Bitmap>(5 * 1024 * 1024) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
}
}

public static My.Utils.ImageLoader getInstance(Context context) {
if (ImageLoader == null) {
ImageLoader = new ImageLoader(context);
}
return ImageLoader;
}

/**
* 对外开放方法
* 1.需要设置的Imageview
* 2.图片的URl
* 3.默认图片
*/
public void setimage(ImageView image, String url, int resid) {
image.setTag(url);
Bitmap bitmap = lruCache.get(url);
if (bitmap != null) {
image.setImageBitmap(bitmap);
return;
} else if (Savedlocal) {
bitmap = Utils.getSavePhone(url);//setSaveToPhone
if (bitmap != null) {
image.setImageBitmap(bitmap);
return;
}
}

if (resid != ID) {
image.setImageResource(resid);
} else {
image.setImageResource(R.mipmap.ic_launcher);
}
new AsyncImageDown().execute(new Image(url, image, null));
}

public void setimage(ImageView image, String url, Bitmap bitmap1) {
image.setTag(url);
Bitmap bitmap = lruCache.get(url);
if (bitmap != null) {
image.setImageBitmap(bitmap);
return;
} else if (Savedlocal) {
bitmap = Utils.getSavePhone(url);//setSaveToPhone
if (bitmap != null) {
image.setImageBitmap(bitmap);
return;
}
}
if (bitmap1 != null) {
image.setImageBitmap(bitmap1);
} else {
image.setImageResource(R.mipmap.ic_launcher);
}
new AsyncImageDown().execute(new Image(url, image, null));
}

public void setimage(ImageView image, String url, Drawable drawable) {
image.setTag(url);
Bitmap bitmap = lruCache.get(url);
if (bitmap != null) {
image.setImageBitmap(bitmap);
return;
} else if (Savedlocal) {
bitmap = Utils.getSavePhone(url);//setSaveToPhone
if (bitmap != null) {
image.setImageBitmap(bitmap);
return;
}
}
if (drawable != null) {
image.setImageDrawable(drawable);
} else {
image.setImageResource(R.mipmap.ic_launcher);
}
new AsyncImageDown().execute(new Image(url, image, null));
}

/**
* 清空数据缓存
*/
public void evictAll() {
lruCache.evictAll();
}

private class AsyncImageDown extends AsyncTask<Image, Void, Image> {

@Override
protected Image doInBackground(Image... images) {
//url imaeg
Image image = images[0];
try {
Bitmap bitmap = HttpUtils.getImageFromNet(image.getUrl());
if (bitmap != null && image.getUrl() != null) {
lruCache.put(image.getUrl(), bitmap);
if (Savedlocal) {
Utils.setSaveToPhone(image.getUrl(), bitmap);
}
image.setBitmap(bitmap);
return image;
}
} catch (IOException e) {
e.printStackTrace();
Log.d("测试", "ImageLoader+AsyncImageDown+doInBackground+图片请求出错" + e.toString());
}
return null;
}

@Override
protected void onPostExecute(Image image) {
if (image != null && image.getBitmap() != null && image.getUrl().equalsIgnoreCase((String) image.getImageView().getTag())) {
image.getImageView().setImageBitmap(image.getBitmap());
}
}
}

public void setSavedlocal(boolean savedlocal) {
Savedlocal = savedlocal;
}

private class Image {
private String url;
private ImageView imageView;
private Bitmap bitmap;

public Image(String url, ImageView imageView, Bitmap bitmap) {
this.url = url;
this.imageView = imageView;
this.bitmap = bitmap;
}

public Bitmap getBitmap() {
return bitmap;
}

public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public ImageView getImageView() {
return imageView;
}

public void setImageView(ImageView imageView) {
this.imageView = imageView;
}
}

}


另外还有一些上文中用到的方法

/**
* 保存图片到手机内存
*
* @param filename
* @param bitmap
* @return
*/
public static void setSaveToPhone(String filename,
Bitmap bitmap) {
filename = filename.replace("/", "");

String path = getPath() + "/" + filename;
File file = new File(path);

if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}

try {

ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] bytes = baos.toByteArray();

FileOutputStream out = new FileOutputStream(path);
out.write(bytes);

out.flush();
out.close();
baos.close();
} catch (Exception e) {
i(e.toString() + "utils-保存图片到手机内存-保存出错");
}
}

/**
* 从本地读取图片
*/
public static Bitmap getSavePhone(String filename) {
filename = filename.replace("/", "");

String path = getPath() + "/" + filename;
try {
FileInputStream in = new FileInputStream(path);
Bitmap bitmap = BitmapFactory.decodeStream(in);
in.close();
return bitmap;
} catch (Exception e) {
}
return null;
}
public static String getPath() {
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/wkk");
if (!file.exists() || !file.isDirectory()) {
file.mkdirs();
}
return file.getPath();
}

/**
* 根据url连接网络 获取图片
*
* @param url
* @return
* @throws IOException
*/
public static Bitmap getImageFromNet(String url) throws IOException {
HttpURLConnection conn = null;
URL mURL = new URL(url);// 创建一个ur对象
// 得到http的链接对象
conn = (HttpURLConnection) mURL.openConnection();
conn.setRequestMethod("GET");// 设置请求的方法为Get
conn.setConnectTimeout(10000);// 设置链接服务器的超时时间 如果超过10秒钟没有链接 抛异常
conn.setReadTimeout(10000);// 设置读取数据超时时间
conn.connect();// 开始链接
int responseCode = conn.getResponseCode();// 得到服务器相应码
if (responseCode == 200) {
// 访问成功
InputStream is = conn.getInputStream();// 获得服务器返回的流
Bitmap bitmap = BitmapFactory.decodeStream(is);// 根据流创建一个Bitmap位图对象
is.close();
return bitmap;
} else {
Utils.d("测试", "访问失败:responseCode=" + responseCode);
}
retur
ace9
n null;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: