自定义界面组件
App 开发中有可能使用到大量的UI组件,除了 Hippy SDK 已包括其中常用的部分,如View、Text、Image 等,我们仍可能需要对 UI 组件进行扩展封装。
组件扩展
我们将以MyView为例,从头介绍如何扩展组件。
扩展组件包括:
- 扩展
HippyViewController。 - 实现
createViewImpl方法、 - 实现
Props设置方法。 - 手势事件处理。
- 注册
HippyViewController。
HippyViewController 是一个视图管理的基类(如果是ViewGroup的组件,基类为 HippyGroupController)。 在这个例子中我们需要创建一个 MyViewController 类,它继承 HippyViewController<MyView>。MyView 是被管理的UI组件类型,它应该是一个 Android View 或者 ViewGroup。 @HippyController 注解用来定义导出给JS使用时的组件信息。
实现属性 Props 方法
需要接收 JS 设置的属性,需要实现带有 @HippyControllerProps 注解的方法。
@HippyControllerProps 可用参数包括:
name(必须):导出给JS的属性名称。defaultType(必须):默认的数据类型。取值包括HippyControllerProps.BOOLEAN、HippyControllerProps.NUMBER、HippyControllerProps.STRING、HippyControllerProps.DEFAULT、HippyControllerProps.ARRAY、HippyControllerProps.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);
}
源码
UIManagerModulehippy更新属性值的入口
@HippyMethod(name = "updateNode")
public void updateNode(int rootID, HippyArray updateArray) {
...
/* 分析1 */
domManager.updateNode(id, props, hippyRootView);
}
- */ 分析1 */
DomManager**更新具体节点的属性值
public void updateNode(final int id, HippyMap map, HippyRootView hippyRootView) {
DomNode node = mNodeRegistry.getNode(id);
...
/* 分析2 */
mDomStyleUpdateManager.updateStyle(node, hippyMap);
...
}
- */ 分析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));
}
}
}
}
- */ 分析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);
}
}
本文介绍了在App开发中如何使用HippySDK扩展自定义UI组件,例如创建MyView,并详细讲述了扩展过程,包括实现HippyViewController,设置Props,以及处理手势事件。同时,文章深入解析了属性更新的流程,从UIManagerModule的updateNode方法,到DomManager和DomUpdateManager如何处理属性更新,特别是@HippyControllerProps注解在其中的作用。
534

被折叠的 条评论
为什么被折叠?



