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

自定义界面组件

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使用时的组件信息。

@HippyController(name = "MyView")
public class MyViewController extends HippyViewController<MyView>
{
    ...
}

实现 createViewImpl 方法

当需要创建对视图时,引擎会调用 createViewImpl 方法。

@Override
protected View createViewImpl(Context context)
{
    // context实际类型为HippyInstanceContext
    return new MyView(context);
}

源码

  1. UIManagerModule hippy创建终端View入口
@HippyMethod(name = "createNode")
public void createNode(int rootID, HippyArray hippyArray) {
  HippyRootView hippyRootView = mContext.getInstance(rootID);
  DomManager domManager = this.mContext.getDomManager();
  if (hippyArray != null && hippyRootView != null && domManager != null) {
    int len = hippyArray.size();
    for (int i = 0; i < len; i++) {
      ...
      String className = (String) nodeArray.get(NAME);
      String tagName = (String) nodeArray.get(TAG_NAME);
      HippyMap props = (HippyMap) nodeArray.get(PROPS);
      /* 分析1 */
      domManager.createNode(hippyRootView, rootID, tag, pTag, index, className, tagName, props);
    }
  }
}
  1. / 分析1 / DomManager 创建Dom节点,如果不是懒加载立即创建View
public void createNode(final HippyRootView hippyRootView, int rootId, final int id, int pid, int index, final String className, String tagName, HippyMap map) {
  	...
		addDispatchTask(new IDomExecutor() {
  		@Override
  		public void exec() { 
        /* 分析2 */
        mRenderManager.createPreView(hippyRootView, id,  
      		nativeParentNode.getId(), childIndex.mIndex,className, newProps);
      }
		});

		addUITask(new IDomExecutor() {
        @Override
        public void exec() {
          mRenderManager.createNode(hippyRootView, id, nativeParentNode.getId(), 
              childIndex.mIndex, className, newProps);
        }
      });
  		...
}
  1. / 分析2 / ControllerManager 如果不是懒加载立即创建View
public void createPreView(HippyRootView hippyRootView, int id, int pid, int mIndex,
    String className, HippyMap newProps) {
	...
  if (!isLazy) {
    /* 分析3 */
    mControllerManager.createPreView(hippyRootView, id, className, newProps);
  }
}
  1. / 分析3 / ControllerManager
public void createPreView(HippyRootView rootView, int id, String className,
    HippyMap initialProps) {
  /* 分析3 a */
  View view = mControllerRegistry.getView(id);
  if (view == null) {
    /* 分析3 b */
    // 若无缓存,则获取Controller重新创建并缓存view
    HippyViewController controller = mControllerRegistry.getViewController(className);
    /* 分析4 */
    view = controller.createView(rootView, id, mContext, className, initialProps);
		...
  }
}

/* 分析3 a */ 
// 若无缓存,则认为是根节点
public View getView(int id) {
  View view = mViews.get(id);
  if (view == null) {
    view = mRoots.get(id);
  }
  return view;
}

/* 分析3 b */
// ControllerManager 被创建时会调用 processControllers 方法,其中会调用 addControllers 方法。
// 此方法会将 将Hippy包中的HippyViewController注册到ControllerRegistry中
// getViewController 实际返回的就是 HippyViewController
public void addControllers(List<HippyAPIProvider> hippyPackages) {
  ...
  // 循环处理所有注册表
  for (HippyAPIProvider hippyPackage : hippyPackages) {
    List<Class<? extends HippyViewController>> components = hippyPackage.getControllers();
    ...
    for (Class hippyComponent : components) {
        ...
        ControllerHolder holder = new ControllerHolder(
            (HippyViewController) hippyComponent.newInstance(), lazy);
      
      	// 维护 name - ViewController 的 Map 以注册 Controller
        mControllerRegistry.addControllerHolder(name, holder);
      	// 允许注册多个别名
        if (names.length > 0) {
          for (String s : names) {
            mControllerRegistry.addControllerHolder(s, holder);
          }
        }
  		}
  }
}
  1. / 分析4 / class HippyViewController<T extends View & HippyViewBase> 优先使用带参数的重载方法。
public View createView(HippyRootView rootView, int id, HippyEngineContext hippyEngineContext,
    String className,
    HippyMap initialProps) {
  ...
  if (rootView != null) {
    Context rootViewContext = rootView.getContext();
    
    // CustomViewCreator" <==> 宿主自定义的一个HippyCustomViewCreator
    // (这个creator还得通过ModuleParams.Builder.setCustomViewCreator来指定才行)
    if (rootViewContext instanceof HippyInstanceContext) {
      @SuppressWarnings("rawtypes") Map nativeParam = ((HippyInstanceContext) rootViewContext)
          .getNativeParams();
      if (nativeParam != null) {
        Object object = nativeParam.get(HippyCustomViewCreator.HIPPY_CUSTOM_VIEW_CREATOR);
        if (object instanceof HippyCustomViewCreator) {
          view = ((HippyCustomViewCreator) object)
              .createCustomView(className, rootView.getContext(), initialProps);
        }
      }
    }
    
    if (view == null) {
      view = createViewImpl(rootView.getContext(), initialProps);
      if (view == null) {
        view = createViewImpl(rootView.getContext());
      }
    }
		...
  }
  return view;
}


protected abstract View createViewImpl(Context context);

protected View createViewImpl(Context context, HippyMap iniProps) {
  return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小黄才不管那么多

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

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

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

打赏作者

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

抵扣说明:

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

余额充值