Android ListView,GridView,RecyclerView图片加载错位闪动问题解决办法
来源:互联网 发布:古诗软件下载 编辑:程序博客网 时间:2024/04/28 08:16
最近看了一下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;/** * 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); } return null; }
2 0
- Android ListView,GridView,RecyclerView图片加载错位闪动问题解决办法
- Android之ListView图片加载错位问题解决
- Android开发教程--listview异步加载图片错位问题解决
- android中ListView异步加载图片时的图片错位问题解决方案
- android中ListView异步加载图片时的图片错位问题解决方案(1)
- android中ListView异步加载图片时的图片错位问题解决方案
- android中ListView异步加载图片时的图片错位问题解决方案
- Android ListView GridView 错位
- ListView异步加载图片--图片缓存和错位问题解决方案
- ListView异步加载图片--图片缓存和错位问题解决方案
- Android ListView加载图片错位的问题
- android listview 加载图片错乱(错位)(2)
- android listview 加载图片错乱(错位)
- Android ListView异步加载图片错位问题
- Android错误之ListView加载错位_ListView图片错位
- ListView GridView图片错位处理
- Android ListView图片异步加载时,图片错位的问题
- 【Android】ListView加载网络图片(解决图片错位问题)
- 如何使用Xcode的Targets来管理开发和生产版本的构建
- eclipse中配置Tomcat并启动服务器发布项目
- 架构高性能网站秘笈(二)——动态内容缓存
- java 单利模式的几种实现方法
- 关于Android开发的40条优化建议
- Android ListView,GridView,RecyclerView图片加载错位闪动问题解决办法
- popOver 弹出框简单使用(仿QQ弹出框)
- 架构高性能网站秘笈(三)——浏览器缓存
- BZOJ3935: Rbtree
- for循环的执行顺序
- C# 中的委托和事件
- Android App 性能优化实践
- 背包问题
- 架构高性能网站秘笈(四)——反向代理缓存