1, the preface

In the last article we introduced the details of the Weex SDK source code for reference. Is the CURRENT Weex SDK optimal? As technology RD, we must have awe in our hearts: art is endless, gradually reflect in the process of learning, to find the optimal solution. So today we will talk about the details of Weex SDK that can be optimized.

2. Reflection acquisition method

As we all know for Weex, JS engine and Native interaction is essentially method call, the final call is inevitably reflection, but method acquisition is reflection this point there is a lot of room for optimization.

Remember how we used the Module component:

  • Inheritance WXModule;
  • Write the function body;
  • Comment @jsmethod on the function body;

These annotated functions can be used to interact with Js. Let’s recall the Module registration code. There are Native registration and Js registration respectively.

  @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 ()) {// getMethod // iterates all the annotations availablein the method
        forAnno (an Annotation: method. GetDeclaredAnnotations ()) {/ / method is Annotationif(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())); // encapsulate as a MethodInvoker objectbreak;
            }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;
  }  
Copy the code

As you can see, the Module registration process must be relatively time-consuming, and the more modules it takes, the longer it takes, especially during the application startup phase. The same is true for the other Component, with the @Component annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
  boolean lazyload() default true;
}
Copy the code

The difference is that: for Native registration, there will be lazy loading judgment, but the effect is general, because the Js side has been generated once before the registration:

  @Override
  public void loadIfNonLazy() {
    Annotation[] annotations = mClz.getDeclaredAnnotations();
    for (Annotation annotation :
      annotations) {
      if(annotation instanceof Component){// Lazy loading oversteps this step for nowif(! ((Component) annotation).lazyload() && mMethodInvokers == null){ generate(); }return; }}}Copy the code

So how to solve the reflection cost performance plus time disadvantage? Here are two solutions for reference:

  • The Weex is initialized asynchronously. Most applications use Weex. The Weex is not used for the entire App. This is easy to do because apps have screen time to use;
  • It is also possible to change the runtime annotations of Weex to compile-time annotations in light of the improvements in different versions of EventBus. This is a much better way to move reflection from runtime to compile-time and eliminates the need for asynchronous initialization.

3, the problem of adaptation

For Weex, the default display width is set to 750px as the adaptation standard.

  @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);
      returnRealPx > 0.005 && realPx < 1? 1: (float) Math.rint(realPx); }}Copy the code

One development detail: how do I know how much PX I need to put in my Vue layout code? If the standard given by UI is not 750, you need to use meters to calculate.

Solution:

  • The specification uses a uniform page adaptation guarantee, such as out of the map according to 750 or 720 (modify Weex adaptation code);
  • Modify Weex webpack-loader, or use the same layout unit as Android native DP (front-end students need to write a tool);

4. Basic ability is not good enough

This has been mentioned in the Module source code parsing before, such as the ability to network requests, whether the use of thread pools or support for caching, protocols, etc., is very general. The same goes for other basic abilities like Stroage and other modules.

For Weex, we actually only need to preserve the Js engine’s ability to interact with Native. The rest are all simple abilities Weex does to attract developers. The realistic requirement is to remove this code, bridge over the native capabilities, and reduce the number of Apk methods.

5, other

  • CSS support is not perfect, some effects on the Web display is different from Native, which requires debugging in Native as far as possible;
  • Regarding documentation, there is no denying that Weex’s ideas and SDK code are excellent, but the documentation is relatively general, some of which are wrong; Some are too simple. For example, for network requests, there is no Post request example, for Component customization, there is no ViewGroup example.

Welcome to the Weex source code analysis project:Weex-Analysis-Project

Welcome to pay attention to wechat public number: regularly share Java, Android dry goods!