Glide-渐进式加载初尝试
Posted 夏雨_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Glide-渐进式加载初尝试相关的知识,希望对你有一定的参考价值。
前言
前面我们讲解了渐进式加载的基础,接下来我们就讲一下在app中具体如何实现渐进式加载
1.基础
关于渐进式加载的基础知识,我们已经在前面讲解过了,这里就不重复讲解了,但是不代表不重要.
http://blog.csdn.net/yulyu/article/details/61915471
2.背景
android图片加载主要有四大框架,但是只有Fresco框架是可以支持渐进式加载(需要设置)
笔者是由于项目已经使用Glide,且跟换框架成本太大,所以才尝试用Glide实现渐进式加载,但是Glide本身框架目前是不适合做渐进式加载,里面的请求是将整个InputStream转化为bitmap后才通过回调设置给ImageView,这个过程只能走一次.笔者做了很多尝试来让Glide实现渐进式加载,虽然最后实现了这个功能,但是会破坏Glide的结构,影响内部的一些优化和设置,比如缓存和防止错位等,所以这里就不介绍这个实现过程了,但是在这个过程中,使用到一些实现渐进式加载的操作,可以介绍一下.
3.实现
首先我们定义一个类,来通过网络请求来获取InputStream
(HttpUrlFetcher是glide里面的一个实现类,这里将里面的代码简化一下,拿来使用)
//HttpUrlFetcher.java
public class HttpUrlFetcher
private static final String TAG = "HttpUrlFetcher";
private HttpURLConnection urlConnection;
private int size;
public int getSize()
return size;
public InputStream loadData(URL url)
throws IOException
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
size = urlConnection.getContentLength();
final int statusCode = urlConnection.getResponseCode();
if (statusCode / 100 == 2)
return urlConnection.getInputStream();
return null;
找到控件和设置图片链接(此链接的图片是支持渐进式加载的JPEG图片)
//MainActivity
url = "http://www.reasoft.com/tutorials/web/img/progress.jpg";
iv1 = (ImageView) findViewById(R.id.iv1);
在子线程中请求网络并实现渐进式加载
//MainActivity.java
public void show(View v)
isCancel = false;
new Thread(new Runnable()
@Override
public void run()
try
//网络请求
InputStream inputStream = httpUrl.loadData(new URL(url));
//创建一个和总数据一样大的数组来当容器
byte[] bytes = new byte[httpUrl.getSize()];
byte lastOne = 0;
byte lastTwo = 0;
int offest = 0;
while (!isCancel)
//本次读取的字节
byte[] get = getBytes(inputStream);
//放入本次读取的数据
System.arraycopy(get, 0, bytes, offest, get.length);
offest = offest + get.length;
//记录最后两位字符
lastOne = bytes[offest - 1];
lastTwo = bytes[offest - 2];
//替换掉最后两个字节为FFD9,否则无法转化成bitmap
bytes[offest - 2] = -1;
bytes[offest - 1] = -39;
//生成bitmap
Bitmap result = BitmapFactory.decodeByteArray(bytes, 0, offest);
//还原最后两个字节
bytes[offest - 2] = lastTwo;
bytes[offest - 1] = lastOne;
Message obtain = Message.obtain();
Bundle bundle = new Bundle();
bundle.putParcelable(BITMAP, result);
obtain.setData(bundle);
handler.sendMessage(obtain);
catch (IOException e)
e.printStackTrace();
).start();
//MainActivity.java
private Handler handler = new Handler()
@Override
public void handleMessage(Message msg)
super.handleMessage(msg);
Bitmap bitmap = msg.getData().getParcelable(BITMAP);
if (bitmap != null)
iv1.setImageBitmap(bitmap);
;
//MainActivity.java
public static byte[] getBytes(InputStream is) throws IOException
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
//这里设置每次读取的数量,设置小一点是为了让效果更明显
byte[] buffer = new byte[10]; // 用数据装
int len = -1;
//要实现比较理想的渐进式加载效果,其实不应该写死每次读取量,应该是根据FFDA来判断读到第几帧了,然后决定是否需要显示了
if ((len = is.read(buffer)) != -1)
outstream.write(buffer, 0, len);
else
is.close();
outstream.close();
// 关闭流一定要记得。
return outstream.toByteArray();
这里有几个地方要注意的 :
- 1.BitmapFactory.decodeByteArray方法读取的字节数组,jpg文件开头得是FFD8,结尾得是FFD9,不然的话会返回null,所以这边在每次解析的时候都将最后两位临时换成FFD9
- 2.这里 FF D9是十六进制的,需要转换为二进制,并且取补码,最后的字节是 -1,-39
- 3.记得增加网络权限
4.其他
本节代码很多地方写得不严禁,效率也不高,目的主要是介绍如何实现渐进式加载.但是笔者认为java在处理这类情况时,其实本身效率并不高,在实际项目使用中,如果对性能要求比较高的话,这类操作还是用C语言等底层来写,Android只是通过JNI来调用,这样更加合理和高效.
5.0 Demo源码
https://github.com/yulyu2008/ProgressiveDemo
热门文章
- Glide-源码详解
- 渐进式加载-基础讲解
- 活用productFlavors
- onTouch事件传递
- 那些年我们解决滑动冲突时遇过的坑
- 进程间通信–AIDL
- 序列化–Serializable与Parcelable
- 如何解决内存溢出以及内存泄漏
- Okhttputils终极封装
- FaceBook推出的调试神器
- Android代码优化工具
- Glide-入门教程
- Glide-图片预处理(圆角,高斯模糊等)
- Glide-图片的压缩
- Glide-内存缓存与磁盘缓存
- Glide-自定义缓存
以上是关于Glide-渐进式加载初尝试的主要内容,如果未能解决你的问题,请参考以下文章