Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%
系列文章
前言
在Android布局優(yōu)化(一)從布局加載原理說起中我們說到了布局加載的兩大性能瓶頸,通過IO操作將XML加載到內(nèi)存中并進行解析和通過反射創(chuàng)建View。這里介紹一種避免運行時通過IO操作讀取布局文件的“黑科技”—X2C。個人認為這個技術(shù)在實際項目中使用可能會需要處理一些兼容性問題,但是從技術(shù)人員的思維發(fā)散的角度,我認為這其中的一些思想還是很值得學(xué)習和借鑒的
背景
一般大家在寫頁面時都是通過xml寫布局,通過setContentView、或LayoutInflater.from(context).inflate方法將xml布局加載到內(nèi)存中
優(yōu)點
可維護性好
支持即時預(yù)覽
代碼結(jié)構(gòu)清晰
缺點
讀取xml很耗時
遞歸解析xml較耗時
反射生成對象的耗時是new的3倍以上
我們團隊在這個問題上也探索過很多解決方案,一度走到了另一個極端,完全廢棄xml,所有控件通過java來new,甚至直接在canvas里繪制,這樣雖然性能確實提升了,但是代碼已經(jīng)沒有了一丁點可讀性,可維護性。 ?我們后來反思代碼到底是給機器看的,還是給人看的??也許X2C已經(jīng)給了我們一個答案
X2C
為了即保留xml的優(yōu)點,又解決它帶來的性能問題,我們開發(fā)了X2C方案。即在編譯生成APK期間,將需要翻譯的layout翻譯生成對應(yīng)的java文件,這樣對于開發(fā)人員來說寫布局還是寫原來的xml,但對于程序來說,運行時加載的是對應(yīng)的java文件。 ????我們采用APT(Annotation Processor Tool)+ JavaPoet技術(shù)來完成編譯期間【注解】->【解注解】->【翻譯xml】->【生成java】整個流程的操作。
性能對比
在開發(fā)集成完之后我們做了簡單的測試,性能對比如下
加載方式
次數(shù)
平均加載時間
XML
100
30
X2C
100
11
集成使用
1.導(dǎo)入依賴
在module的build.gradle文件添加依賴
annotationProcessor 'com.zhangyue.we:x2c-apt:1.1.2'
implementation 'com.zhangyue.we:x2c-lib:1.0.6'
2.添加注解
在使用布局的任意java類或方法添加注解即可
@Xml(layouts = "activity_main")
3.配置自定義屬性(沒有可不配)
在module下建立X2C_CONFIG.xml文件,里面配置定義屬性和方法的映射關(guān)系,如果接收者是view,則寫view.否則填params.
4.通過X2C加載布局
在原先使用setContentView或inflate的地方替換,如下:
this.setContentView(R.layout.activity_main); --> X2C.setContentView(this, R.layout.activity_main);
LayoutInflater.from(this).inflate(R.layout.activity_main,null); --> X2C.inflate(this,R.layout.activity_main,null);
過程文件
原始的xml
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp">
android:id="@+id/head"
layout="@layout/head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
android:id="@+id/ccc"
style="@style/bb"
android:layout_below="@id/head" />
生成的java文件
/**
* WARN!!! dont edit this file
* translate from {@link com.zhangyue.we.x2c.demo.R.layout.activity_main}
* autho chengwei
* email chengwei@zhangyue.com
*/
public class X2C_2131296281_Activity_Main implements IViewCreator {
@Override
public View createView(Context ctx, int layoutId) {
Resources res = ctx.getResources();
RelativeLayout relativeLayout0 = new RelativeLayout(ctx);
relativeLayout0.setPadding((int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,res.getDisplayMetrics())),0,0,0);
View view1 =(View) new X2C_2131296283_Head().createView(ctx,0);
RelativeLayout.LayoutParams layoutParam1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
view1.setLayoutParams(layoutParam1);
relativeLayout0.addView(view1);
view1.setId(R.id.head);
layoutParam1.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE);
ImageView imageView2 = new ImageView(ctx);
RelativeLayout.LayoutParams layoutParam2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,res.getDisplayMetrics())));
imageView2.setLayoutParams(layoutParam2);
relativeLayout0.addView(imageView2);
imageView2.setId(R.id.ccc);
layoutParam2.addRule(RelativeLayout.BELOW,R.id.head);
return relativeLayout0;
}
}
生成的映射文件
/**
* WARN!!! don't edit this file
*
* author chengwei
* email chengwei@zhangyue.com
*/
public class X2C127_activity implements IViewCreator {
@Override
public View createView(Context context) {
View view = null ;
int sdk = Build.VERSION.SDK_INT;
int orientation = context.getResources().getConfiguration().orientation;
boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE;
if (isLandscape) {
view = new com.zhangyue.we.x2c.layouts.land.X2C127_Activity().createView(context);
} else if (sdk >= 27) {
view = new com.zhangyue.we.x2c.layouts.v27.X2C127_Activity().createView(context);
} else if (sdk >= 21) {
view = new com.zhangyue.we.x2c.layouts.v21.X2C127_Activity().createView(context);
} else {
view = new com.zhangyue.we.x2c.layouts.X2C127_Activity().createView(context);
}
return view;
}
}
不支持
merge標簽 ,在編譯期間無法確定xml的parent,所以無法支持
系統(tǒng)style,在編譯期間只能查到應(yīng)用的style列表,無法查詢系統(tǒng)style,所以只支持應(yīng)用內(nèi)style
支持
兼容ButterKnifer
兼容DataBinding
各種系統(tǒng)控件、自定義控件
include標簽
viewStub標簽
fragment標簽
應(yīng)用style
自定義屬性
系統(tǒng)屬性
屬性名稱
屬性名稱
android:textSize
app:layout_constraintRight_toLeftOf
android:textColor
app:layout_constraintBottom_toTopOf
android:text
app:layout_constraintTop_toTopOf
android:background
app:layout_constrainedHeight
總結(jié)
以上是生活随笔為你收集整理的Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android图标随着进度条动画,And
- 下一篇: android 多语言不起作用,Andr