在上一篇文章中咱們介紹了Weex SDK源碼中可借鑑的細節,那麼如今的Weex SDK已是最優的嗎?做爲技術RD,咱們心中必定要有敬畏:藝無止境,學習的過程當中逐漸反思,尋找最優解。那麼咱們今天就來講說Weex SDK中有哪些能夠優化的細節。前端
你們知道對於Weex來講,JS引擎與Native的交互本質上就是方法的調用,最終調用的時候必然是反射無疑,可是方法的獲取也是反射這一點存在很大優化空間。webpack
先回憶下咱們使用Module組件的方法:git
而這些被打上註解的函數則能夠拿來與Js進行交互,咱們回憶下Module註冊的代碼,分別有Native的註冊和Js的註冊,註冊有一步是獲取Module組件中打上註解的方法:github
@Override
public String[] getMethods() {
if (mMethodMap == null) {
generateMethodMap();
}
Set<String> keys = mMethodMap.keySet();
return keys.toArray(new String[keys.size()]);
}
private void generateMethodMap() {
if(WXEnvironment.isApkDebugable()) {
WXLogUtils.d(TAG, "extractMethodNames:" + mClazz.getSimpleName());
}
HashMap<String, Invoker> methodMap = new HashMap<>();
try {
for (Method method : mClazz.getMethods()) {// 拿到方法
// iterates all the annotations available in the method
for (Annotation anno : method.getDeclaredAnnotations()) {// 方法是否被打上註解
if (anno != null) {
if(anno instanceof JSMethod) {
JSMethod methodAnnotation = (JSMethod) anno;
String name = JSMethod.NOT_SET.equals(methodAnnotation.alias())? method.getName():methodAnnotation.alias();
methodMap.put(name, new MethodInvoker(method, methodAnnotation.uiThread()));// 封裝成MethodInvoker對象
break;
}else if(anno instanceof WXModuleAnno) {
WXModuleAnno methodAnnotation = (WXModuleAnno)anno;
methodMap.put(method.getName(), new MethodInvoker(method,methodAnnotation.runOnUIThread()));
break;
}
}
}
}
} catch (Throwable e) {
WXLogUtils.e("[WXModuleManager] extractMethodNames:", e);
}
mMethodMap = methodMap;
}
複製代碼
能夠看到,Module註冊的過程一定是相對耗時的,而Module越多時間也越長,應用啓動階段註冊的話尤其明顯。而對於另外一個組件Component基本也是同樣的,只不過多了個註解@Component:web
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
boolean lazyload() default true;
}
複製代碼
區別在於:對於Native註冊,會有懶加載的判斷,不過效果通常,由於Js端註冊前已經生成一次了:緩存
@Override
public void loadIfNonLazy() {
Annotation[] annotations = mClz.getDeclaredAnnotations();
for (Annotation annotation :
annotations) {
if (annotation instanceof Component){
// 懶加載則暫時跨過這步
if(!((Component) annotation).lazyload() && mMethodInvokers == null){
generate();
}
return;
}
}
}
複製代碼
那麼反射消耗性能加上耗時的缺點應該如何解決呢?這裏提供兩條解決途徑供參考:bash
對於Weex,它默認的將顯示的寬度設置爲750px做爲適配的標準。微信
@Deprecated
public static float getRealPxByWidth(float pxValue) {
return getRealPxByWidth(pxValue,750);
}
public static float getRealPxByWidth(float pxValue,int customViewport) {
if (Float.isNaN(pxValue)) {
return pxValue;
}
if (mUseWebPx) {
return (float) Math.rint(pxValue);
} else {
float realPx = (pxValue * getScreenWidth() / customViewport);
return realPx > 0.005 && realPx < 1 ? 1 : (float) Math.rint(realPx);
}
}
複製代碼
那提一個開發中的細節問題:我怎麼知道須要在Vue的佈局代碼中寫多少px呢?若是UI同窗給出的不是750標準就須要本身使用公尺去計算。網絡
解決思路:異步
這個以前在Module的源碼解析中其實提到過,好比網絡請求的能力,不論是線程池的使用仍是對緩存、協議等的支持都很通常。類如別的一些基礎能力好比Stroage等模塊也是同樣。
不過這條屬於苛責,以前也總結過對於Weex來講咱們實際上只須要保存其Js引擎與Native的交互能力便可,別的都屬於Weex爲了吸引開發者而作的簡略能力。現實的要求是把這些代碼去掉,本身橋接原生原有的能力,縮減Apk的方法數。
歡迎持續關注Weex源碼分析項目:Weex-Analysis-Project
歡迎關注微信公衆號:按期分享Java、Android乾貨!