先看效果图:
gif图片加载
由于KJFrameForAndroid自带的网络图片加载并不支持gif的显示。所以我们需要自定义一个GifRequest类来作为我们的gif请求类。
首先来看一下主要代码
public class GifRequest extends Request<byte[]> {
@Override
public Response<byte[]> parseNetworkResponse(NetworkResponse response) {
synchronized (sDecodeLock) {
try {
return doParse(response);
} catch (OutOfMemoryError e) {
KJLoger.debug("Caught OOM for %d byte image, url=%s",
response.data.length, getUrl());
return Response.error(new KJHttpException(e));
}
}
}
private Response<byte[]> doParse(NetworkResponse response) {
if (response.data == null) {
return Response.error(new KJHttpException(response));
} else {
Response<byte[]> b = Response.success(response.data, response.headers,
HttpHeaderParser.parseCacheHeaders(mConfig, response));
return b;
}
}
@Override
protected void deliverResponse(Map<String, String> header, byte[] response) {
if (mCallback != null) {
mCallback.onSuccess(response);
}
}
}
功能非常的简单,在doParse()方法中,我们通过判断response.data的内容来得知这次请求是否成功,当请求成功以后,就将这个请求得到的数据通过分发器deliverResponse方法分发到主线程的回调方法中响应。
完整的实现可以参照下文给出的demo源码。
gif图片显示
当图片加载到本地了以后,我们所需要做的就是将上面加载到的gif显示出来。Android的imageview本身是不支持gif显示的,当然,已经有前人帮我们实现了显示gif的功能。这里跟大家推荐两个gif显示的控件:1、使了用jni的gif显示控件; 2、最小体积的显示方式(只有2个类)
这两个类各自的优势就像前面说的,第一个使用了jni,会使apk增大但效率要比第二种使用java代码逐帧解析高很多;第二种自然就是从apk体积上要小了很多,毕竟仅仅2个类就解决了gif的显示。
这两种库的使用方式在下面的源码中我都会给出,大家可以自行选择。
顺便说一下在使用jni那个项目的时候遇到了一个问题,报java.lang.UnsatisfiedLinkError: Couldn't load pl_droidsonroids_gif from loader xxxx findLibrary returned null
就是so文件在项目编译后并没有打包到apk里面去(详细描述见Issue)
就这个问题困扰了我整整一天,最后发现竟然是因为百度推送的gradle声明中加入了下面的代码,查了很久原因才知道这段代码是为了兼容老版本的AndroidStudio,而新版本早就已经不再使用了,删掉就正常了。
task copyNativeLibs(type: Copy) {
from fileTree(dir: 'libs', include: 'armeabi/*.so') into 'build/lib'
}
clean.dependsOn 'cleanCopyNativeLibs'
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
pkgTask.jniFolders = [new File(buildDir, 'lib')]
}
完整代码
有关gif显示的完整demo,我写成了一个module开源在GitHub上,大家可以在这里查看:https://github.com/kymjs/KJGallery
同时跟大家推荐一个移动开发网站:http://www.mobile-open.com/
补充更新
10月19日补充
感谢微博的@折迹 同学的建议,刚刚更新了图片类型的判断方案。(原项目已更新)
之前使用”.gif”扩展名来判断图片确实不是最好方法,现在的判断方法如下所示:
/**
* 获取图片类型
*/
public int getType(byte[] data) {
// Png test:
if (data[1] == 'P' && data[2] == 'N' && data[3] == 'G') {
return TYPE_PNG;
}
// Gif test:
if (data[0] == 'G' && data[1] == 'I' && data[2] == 'F') {
return TYPE_GIF;
}
// JPG test:
if (data[6] == 'J' && data[7] == 'F' && data[8] == 'I'
&& data[9] == 'F') {
return TYPE_JPG;
}
return TYPE_JPG;
}