【Android】Hippy自定义界面组件之实现属性 Props 方法

自定义界面组件

App 开发中有可能使用到大量的UI组件,除了 Hippy SDK 已包括其中常用的部分,如ViewTextImage 等,我们仍可能需要对 UI 组件进行扩展封装。


组件扩展

我们将以MyView为例,从头介绍如何扩展组件。

扩展组件包括:

  1. 扩展 HippyViewController
  2. 实现 createViewImpl方法
  3. 实现 Props 设置方法。
  4. 手势事件处理。
  5. 注册 HippyViewController

HippyViewController 是一个视图管理的基类(如果是ViewGroup的组件,基类为 HippyGroupController)。 在这个例子中我们需要创建一个 MyViewController 类,它继承 HippyViewController<MyView>MyView 是被管理的UI组件类型,它应该是一个 Android View 或者 ViewGroup@HippyController 注解用来定义导出给JS使用时的组件信息。

实现属性 Props 方法

需要接收 JS 设置的属性,需要实现带有 @HippyControllerProps 注解的方法。

@HippyControllerProps 可用参数包括:

  • name(必须):导出给JS的属性名称。
  • defaultType(必须):默认的数据类型。取值包括 HippyControllerProps.BOOLEANHippyControllerProps.NUMBERHippyControllerProps.STRINGHippyControllerProps.DEFAULTHippyControllerProps.ARRAYHippyControllerProps.MAP
  • defaultBoolean:当 defaultType 为 HippyControllerProps.BOOLEAN 时,设置后有效。
  • defaultNumber:当 defaultType 为 HippyControllerProps.NUMBER 时,设置后有效。
  • defaultString:当 defaultType 为 HippyControllerProps.STRING 时,设置后有效。
@HippyControllerProps(name = "text", defaultType = HippyControllerProps.STRING, defaultString = "")
public void setText(MyView textView, String text)
{
    textView.setText(text);
}

源码

  1. UIManagerModule hippy更新属性值的入口
@HippyMethod(name = "updateNode")
public void updateNode(int rootID, HippyArray updateArray) {
  ...
  /* 分析1 */
  domManager.updateNode(id, props, hippyRootView);
}
  1. */ 分析1 */DomManager**更新具体节点的属性值
public void updateNode(final int id, HippyMap map, HippyRootView hippyRootView) {
  DomNode node = mNodeRegistry.getNode(id);
	...
  /* 分析2 */
  mDomStyleUpdateManager.updateStyle(node, hippyMap);
  ...
}
  1. */ 分析2 */DomUpdateManager**具体更新逻辑
public void updateStyle(T t, HippyMap hippyMap) {
  // 若无更新逻辑则结束
  if (hippyMap == null) {
    return;
  }
  
  // 优先从缓存中读取,若无则更新缓存
  Class cla = t.getClass();
  Map<String, StyleMethod> methods = CLASS_STYLE_METHOD.get(cla);
  if (methods == null) {
    /* 分析3 */
    methods = findStyleMethod(cla);
  }
  
  Set<String> styles = hippyMap.keySet();
  for (String style : styles) {
    StyleMethod styleMethodHolder = methods.get(style);
    // 如果 methods 中不存在名为 style 的方法,说明该组件不支持该样式
    // 但是如果该样式名为 "style",则说明是样式集合,需要进一步调用 updateStyle 方法进行更新。
    if (styleMethodHolder != null) {
      {
        try {
          // 若 hippyMap 中没有 style 的映射就根据 styleMethodHolder 中保存的默认值调用方法,
  				// 否则根据 hippyMap 中保存的值调用方法
          if (hippyMap.get(style) == null) {
            switch (styleMethodHolder.mDefaultType) {
              case HippyControllerProps.BOOLEAN:
                styleMethodHolder.mMethod.invoke(t, styleMethodHolder.mDefaultBoolean);
                break;
              case HippyControllerProps.NUMBER:
                styleMethodHolder.mMethod.invoke(t,
                    ArgumentUtils.parseArgument(styleMethodHolder.mParamTypes[0],
                        styleMethodHolder.mDefaultNumber));
                break;
              case HippyControllerProps.STRING:
                styleMethodHolder.mMethod.invoke(t, styleMethodHolder.mDefaultString);
                break;
              default:
                Object o = null;
                //noinspection ConstantConditions
                styleMethodHolder.mMethod.invoke(t, o);
                break;
            }
          } else {
            styleMethodHolder.mMethod.invoke(t,
                ArgumentUtils.parseArgument(styleMethodHolder.mParamTypes[0], hippyMap, style));
          }
        } catch (Throwable e) {
          LogUtils.e("ControllerUpdateManager", e.getMessage(), e);
          e.printStackTrace();
        }
      }
    } else {
      if (hippyMap.get(style) instanceof HippyMap && style.equals(NodeProps.STYLE)) {
        updateStyle(t, (HippyMap) hippyMap.get(style));
      }
    }
  }
}
  1. */ 分析3 */DomUpdateManager**查找给定类中所有 @HippyControllerProps 注解的方法
/* 分析3 */
private Map<String, StyleMethod> findStyleMethod(Class cla) {
  Map<String, StyleMethod> hashMap = new HashMap<>();
  findStyleMethod(cla, hashMap);
  return hashMap;
}

private void findStyleMethod(Class cls, Map<String, StyleMethod> hashMap) {
  // 首先从顶级父类查找使用 @HippyControllerProps 注解的方法
  if (cls != StyleNode.class) {
    findStyleMethod(cls.getSuperclass(), hashMap);
  }
  
  // 优先使用缓存,若无缓存则通过反射将带有 @HippyControllerProps 注解的方法添加到缓存以及 结果map 中
  // 若有缓存则将缓存添加到 结果map 中
  Map<String, StyleMethod> methodHolder = CLASS_STYLE_METHOD.get(cls);
  if (methodHolder == null) {
    Method[] methods = cls.getDeclaredMethods();
    for (Method method : methods) {
      HippyControllerProps controllerProps = method.getAnnotation(HippyControllerProps.class);
      if (controllerProps != null) {
        String style = controllerProps.name();
        StyleMethod propsMethodHolder = new StyleMethod();
        propsMethodHolder.mDefaultNumber = controllerProps.defaultNumber();
        propsMethodHolder.mDefaultType = controllerProps.defaultType();
        propsMethodHolder.mDefaultString = controllerProps.defaultString();
        propsMethodHolder.mDefaultBoolean = controllerProps.defaultBoolean();
        propsMethodHolder.mMethod = method;
        propsMethodHolder.mParamTypes = method.getGenericParameterTypes();
        hashMap.put(style, propsMethodHolder);
      }
    }
    // put to CLASS_PROPS_METHOD
    CLASS_STYLE_METHOD.put(cls, new HashMap<>(hashMap));
  } else {
    hashMap.putAll(methodHolder);
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄才不管那么多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值