【Android】Hippy自定义界面组件之更多特性

自定义界面组件

App 开发中有可能使用到大量的UI组件,Hippy SDK 已包括其中常用的部分,如ViewTextImage 等,但这极有可能无法满足你的需求,这就需要对 UI 组件进行扩展封装。


更多特性

处理组件方法调用

在有些场景,JS需要调用组件的一些方法,比如 MyViewchangeColor。这个时候需要在 HippyViewController重载 dispatchFunction 方法来处理JS的方法调用。

public void dispatchFunction(MyView view, String functionName, HippyArray var)
{
    switch (functionName)
    {
        case "changeColor":
            String color = var.getString(0);
            view.setColor(Color.parseColor(color));
            break;
    }
    super.dispatchFunction(view, functionName, var);
}

源码

  1. UIManagerModule 组件方法调用的入口
@HippyMethod(name = "callUIFunction")
public void callUIFunction(HippyArray hippyArray, Promise promise) {
  ...
  int id = hippyArray.getInt(0);
  String functionName = hippyArray.getString(1);
  HippyArray array = hippyArray.getArray(2);
  /* 分析1 */
  domManager.dispatchUIFunction(id, functionName, array, promise);
}
  1. / 分析1 /DomManager 添加任务,使组件方法向下分发
public void dispatchUIFunction(final int id, final String functionName, final HippyArray 		    
                               array,final Promise promise) {
  addNulUITask(new IDomExecutor() {
    @Override
    public void exec() {
      /* 分析2 */
      mRenderManager.dispatchUIFunction(id, functionName, array, promise);
    }
  });
}
  1. / 分析2 /RenderManager 继续向下分发组件方法
public void dispatchUIFunction(int id, String functionName, HippyArray var, Promise promise) {
  RenderNode renderNode = mNodes.get(id);
  ...
  /* 分析3 */
  renderNode.dispatchUIFunction(functionName, var, promise);
  ...
}
  1. / 分析3 /RenderNodemUIFunction中添加组件方法,等待被调用
public void dispatchUIFunction(String functionName, HippyArray parameter, Promise promise) {
  if (mUIFunction == null) {
    mUIFunction = new ArrayList<>();
  }
  mUIFunction.add(new UIFunction(functionName, parameter, promise));
}
  1. RenderNode 节点更新时,调用已经添加的所有组件方法
public void update() {
  ...
  if (mUIFunction != null && mUIFunction.size() > 0) {
    for (int i = 0; i < mUIFunction.size(); i++) {
      UIFunction uiFunction = mUIFunction.get(i);
      /* 分析4 */
      mComponentManager.dispatchUIFunction(mId, mClassName, uiFunction.mFunctionName, 
                                           uiFunction.mParameter,uiFunction.mPromise);
      }
      mUIFunction.clear();
      mUIFunction = null;
    }
  ...
}
  1. / 分析4 /ControllerManager 区分有无回调,调用组件方法
public void dispatchUIFunction(int id, String className, String functionName, HippyArray var,
    Promise promise) {
  HippyViewController hippyViewController = mControllerRegistry.getViewController(className);
  View view = mControllerRegistry.getView(id);
  if (!promise.isCallback()) {
    hippyViewController.dispatchFunction(view, functionName, var);
  } else {
    hippyViewController.dispatchFunction(view, functionName, var, promise);
  }

}
  1. HippyViewController<T extends View & HippyViewBase> 调用到重载方法
public void dispatchFunction(T view, String functionName, HippyArray var) {
}

public void dispatchFunction(T view, String functionName, HippyArray params, Promise promise) {
}

事件回调

Hippy SDK 提供了一个基类 HippyViewEvent,其中封装了UI事件发送的逻辑,只需调用 send 方法即可发送事件到JS对应的组件上。比如我要在 MyViewonAttachedToWindow 的时候发送事件到前端的控件上面。 示例如下:

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    // this is show how to send message to js ui
    HippyMap hippyMap = new HippyMap();
    hippyMap.pushString("test", "code");
    new HippyViewEvent(" onAttachedToWindow").send(this, hippyMap);
}

源码

new HippyViewEvent(" onAttachedToWindow").send(this,hippyMap);
  1. send 方法 会将事件名,参数发送给指定id的组件
public void send(View view, Object param) {
  if (view != null && view.getContext() instanceof HippyInstanceContext) {
    HippyEngineContext context = ((HippyInstanceContext) 
                                  view.getContext()).getEngineContext();
    send(view.getId(), context, param);
  }
}

public void send(int id, HippyEngineContext context, Object param) {
  if (context == null) {
    return;
  }

  HippyModuleManager hmm = context.getModuleManager();
  if (hmm != null) {
    hmm.getJavaScriptModule(EventDispatcher.class).receiveUIComponentEvent(id, mEventName, 
                                                                           param);
  }
}

HippyViewController 的回调函数

  • onAfterUpdateProps:属性更新完成后回调。
  • onBatchComplete:一次上屏操作完成后回调(适用于 ListView 类似的组件,驱动 Adapter刷新等场景)。
  • onViewDestroy:视图被删除前回调(适用于类似回收视图注册的全局监听等场景)。
  • onManageChildComplete:在 HippyGroupController 添加、删除子视图完成后回调。

源码 (以onManageChildComplete为例)

  1. RenderNode 更新节点时触发回调函数 沿着a -> b -> c调用,触发重载的回调函数
public void update() {
  ...
  if (mChildPendingList.size() > 0) {
    Collections.sort(mChildPendingList, new Comparator<RenderNode>() {
      @Override
      public int compare(RenderNode o1, RenderNode o2) {
        return o1.indexFromParent() < o2.indexFromParent() ? -1 : 0;
      }
    });
    for (int i = 0; i < mChildPendingList.size(); i++) {
      RenderNode renderNode = mChildPendingList.get(i);
      mComponentManager.addChild(mId, renderNode.getId(), renderNode.indexFromParent());
    }
    mChildPendingList.clear();
    // 更新子节点则添加标志位
    mNotifyManageChildren = true;
  }
  ...
  // 存在标志位则开始出发回调函数并重置标志位
  if (mNotifyManageChildren) {
    /* a */
    manageChildrenComplete();
    mNotifyManageChildren = false;
  }
  ...
}

/* a */
public void manageChildrenComplete() {
  if (!mIsLazyLoad && !mIsDelete) {
    /* b */
    mComponentManager.onManageChildComplete(mClassName, mId);
  }
}

/* b */
public void onManageChildComplete(String className, int id) {
  HippyViewController hippyViewController = mControllerRegistry.getViewController(className);
  View view = mControllerRegistry.getView(id);
  if (view != null) {
    /* c */
    hippyViewController.onManageChildComplete(view);
  }
}

/* c */
protected void onManageChildComplete(T view) {}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小黄才不管那么多

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

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

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

打赏作者

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

抵扣说明:

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

余额充值