decode / encode
(Android 4.0+)
(Lossless, Transparency, Android 4.2.1+)
https://developer.android.com/guide/appendix/media-formats.html
那么结合文档和实验,大致可以有如下的结论:
-
4.2.1+ 对于webp的decode、encode是完全支持的(包含半透明的webp图)
-
对于4.0+ 到 4.2.1 ,只支持完全不透明的decode、encode的webp图
-
4.0 以下,应该是默认不支持webp了
看到这个结论,那么就是大家的产品最低的支持版本了。
4.2.1起步的话,目前来看,我是不能接受的,所以只有引入so来做低版本兼容了。
(2)兼容so的获取
好在官方已经提供了相关webp支持的源码了,点击下载:
如果你的ndk的知识足够的话,可以自己利用源码,去生成so文件使用。
当然了,你也可以使用前人已经封装好的库:
我们这里选择使用第二个库,这里选择copy它生成的so文件以及辅助类到项目中,你也可以根据其readme打包一个aar出来使用。
首先下载下来webp-android,然后切换到webp-android/src/main/jni
,执行ndk-build
然后等待执行结束,可以在其/webp-android/src/main/libs
目录下copy出你需要的so,如果需要其他cpu架构的so,可以自己修改Application.mk文件。
/webp-android/src/main/libs
.
├── armeabi
│ └── libwebp_evme.so
├── armeabi-v7a
│ └── libwebp_evme.so
└── x86
└── libwebp_evme.so
然后将其WebDecoder的辅助类copy到项目中即可,注意保持原有包名。
ok,然后就可以用它提供的decode的方法了:
WebPDecoder.getInstance().decodeWebP(byte[] encoded)
于是,上述以InputStream为webp图片源的代码可以改写为:
大致的示例代码
InputStream is = getAssets().open(“weixin.webp”);
Bitmap bitmap = null;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
bitmap = WebPDecoder.getInstance().decodeWebP(streamToBytes(is));
} else {
bitmap = BitmapFactory.decodeStream(is);
}
imageView.setImageBitmap(bitmap);
private static byte[] streamToBytes(InputStream is) {
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int len;
try {
while ((len = is.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (java.io.IOException e) {
}
return os.toByteArray();
}
ok,这样就可以对4.2.1以下的webp图片进行decode了。
服务端下发的图片为webp格式,然后app去decode显示即可。
注:webp-android这个库只提供了decode方法,如果需要encode需要自己去添加;建议有时间,看下源码中提供的方法,自己利用源码结合ndk相关知识自己做so文件的生成.
(3)应用中的资源文件
除了上述去加载外部图片的方式以外,还有个使用场景就是将项目中的资源文件直接替换为webp。
简单的使用:
直接将png转化为webp,放到res/drawable目录,我们看看效果
这样就可以了~~
从目前来看有2个选择:
-
仅替换不存在局部透明的图片,如果项目最小版本是4.0,可以不引入so直接使用。
-
全部替换(需要引入so的支持)
第一种,目前来看没什么好介绍的,换图即可。
主要看第二种的处理了,webp-android提供了一种做法是这样的:
<me.everything.webp.WebPImageView
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
webp:webp_src=“@drawable/your_webp_image” />
这样就可以happy的使用webp了。
但是我一点都不happy,使用webp很多都是已经存在的项目,让我去使用自定义类还要加属性,多麻烦,万一发现坑,我还得一个一个换回去,坚决不干。
所以我们需要一种,可以无缝切换的方式,基本不费力也能还原。
最无缝的方式,就是不动原本的布局文件了,那么如何去动态修改ImageView使其支持Webp呢(4.-)?
其实我们的SDK也有类似的做法,比如对很多View支持了tint属性,原本是不支持的,忽然就支持了,怎么做到的呢?
就是在根据布局文件中ImageView标签名称,创建的时候去做了一些手脚,如果你一脸懵逼,可以先看Android 探究 LayoutInflater setFactory。
实际上就是利用LayoutInflaterFactory
了,有了方案,那么代码就好写了:
public class MainActivity extends AppCompatActivity {
private static final int[] LL = new int[]
{ //
android.R.attr.src,//
};
@Override
protected void onCreate(Bundle savedInstanceState) {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN){
LayoutInflaterCompat.setFactory(LayoutInflater.from(this), new LayoutInflaterFactory() {
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
AppCompatDelegate delegate = getDelegate();
View view = delegate.createView(parent, name, context, attrs);
if (view instanceof ImageView) {
ImageView imageView = (ImageView) view;
TypedArray a = context.obtainStyledAttributes(attrs, LL);
int webpSourceResourceID = a.getResourceId(0, 0);
if (webpSourceResourceID == 0) {
return view;
}
InputStream rawImageStream = getResources().openRawResource(webpSourceResourceID);
byte[] data = streamToBytes(rawImageStream);
final Bitmap webpBitmap = WebPDecoder.getInstance().decodeWebP(data);
imageView.setImageBitmap(webpBitmap);
a.recycle();
}
return view;
}
});
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
一般我们的项目中的Activity都存在一个基类,那么直接在其中添加上述代码即可。
大致逻辑为:对于4.2以下的版本,我们设置一个LayoutInflaterFactory
,当创建ImageView的时候,因为AppCompatActivity,ImageView的创建是由上述代码中的delegate指向的对象完成的,我们通过传入attrs,取出用户声明的src属性,经过一系列操作转化为bitmap,最好设置到创建好的ImageView上。
这样,剩下的我们直接将图换成webp就好了,如果发现不适合,只需要去掉这个factory设置的代码即可。
正在我窃喜的时候,忽然发现了一个问题。
就是假设我的资源文件更换并不彻底,还存在部分png的图,但是png的图在4.2以下的版本是不需要上述操作的。
- 那么问题来了,如何区分webp和非webp的图片资源呢?
当然是根据后缀,那么我们现在能获取的仅仅是图片的resId,还能拿到文件完整的名称吗?
让人开心的是,可以拿到的。
TypedValue value = new TypedValue();
getResources().getValue(webpSourceResourceID, value, true);
String resname = value.string.toString().substring(13,
value.string.toString().length());
if (resname.endsWith(“.webp”)) {
// do
}
当然应该也可以通过图片的header信息来判断,header判断这种方式应该会更加精确,具体可以查找下相关代码。
对了,如果你的基类是FragmentActivity,那就不需要去设置什么LayoutFactory了,直接复写其onCreateView方法:
onCreateView(View parent, String name, Context context, AttributeSet attrs) {
final View view = super.onCreateView(parent, name, context, attrs);
if(view == null){
if (name.equals(“ImageView”)) {
view = new ImageView(context,attrs);
}
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
if (view instanceof ImageView) {
ImageView imageView = (ImageView) view;
TypedArray a = context.obtainStyledAttributes(attrs, LL);
int webpSourceResourceID = a.getResourceId(0, 0);
if (webpSourceResourceID == 0) {
return view;
}
TypedValue value = new TypedValue();
getResources().getValue(webpSourceResourceID, value, true);
String resname = value.string.toString().substring(13,
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
框架相关
原生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。现阶段较热门是React、Vue两大框架,两者工作原理上存在共通点,也存在一些不同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。
在框架方面,生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的,在学习的过程可以结合框架的官方文档
CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
Vue框架
知识要点:
1. vue-cli工程
2. vue核心知识点
3. vue-router
4. vuex
5. http请求
6. UI样式
7. 常用功能
8. MVVM设计模式
React框架
知识要点:
1. 基本知识
2. React 组件
3. React Redux
4. React 路由
同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。
在框架方面,生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的,在学习的过程可以结合框架的官方文档
CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
Vue框架
知识要点:
1. vue-cli工程
2. vue核心知识点
3. vue-router
4. vuex
5. http请求
6. UI样式
7. 常用功能
8. MVVM设计模式
[外链图片转存中…(img-Wq6p1Df4-1711897594536)]
React框架
知识要点:
1. 基本知识
2. React 组件
3. React Redux
4. React 路由
[外链图片转存中…(img-po97cYih-1711897594537)]