Weex 自定义 Component 开发这块,官方文档和网上示例都较少涉及。工做所需有所研究,总结此文以飨读者。前端
以下述代码所示,从 WXComponent 继承出来之后,复写四个构造器方法,就能够完成一个最简单可跑固然也显示不了任何东西的 WXComponet。java
须要说明的是 WXComponent 能够指定泛型 T,T extends View,用于指定WXComponent hostView 根布局的类型。这个仍是指定的比较好,在某些进阶用法中会须要这个类型。git
public class DemoWXComponent extends WXComponent<T> { public DemoWXComponent(WXSDKInstance instance, WXVContainer parent, int type, BasicComponentData basicComponentData) { super(instance, parent, type, basicComponentData); } public DemoWXComponent(WXSDKInstance instance, WXVContainer parent, String instanceId, boolean isLazy, BasicComponentData basicComponentData) { super(instance, parent, instanceId, isLazy, basicComponentData); } public DemoWXComponent(WXSDKInstance instance, WXVContainer parent, boolean isLazy, BasicComponentData basicComponentData) { super(instance, parent, isLazy, basicComponentData); } public DemoWXComponent(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) { super(instance, parent, basicComponentData); } }
使用这个 Component 以前,还须要把他注册进 WXSDKEngine。以下所示:
一次注册后,在Android程序销毁以前,能够一直使用这个 Component。无需 unregister,WXSDKEngine 也没有提供 unregister 方法,这是显而易见的,由于当前还未产生任何实例。github
WXSDKEngine.registerComponent("democomponent", DemoWXComponent.class);
值得一提的是 componet 名称,尽可能不要下划线中划线和大写字母,不然可能会踩坑。weex
好,接下来是 Weex JS 代码怎么调用。无需 import,直接使用,只要 register 方法已经被执行过了,以下所示:ide
<democomponent />
若是想要设定 props 怎么办,如 <democomponent source=test/>。布局
那就在 Componet 中增长以下:性能
@WXComponentProp(name = "source") public void setSource(String source) { mSource = source; // or do some things }
weex 会根据外部传入的 props,根据注解调用对应 props 的 set 方法。code
显然,看了第一节,只能保证链路上 weex 自定义 Component 能跑起来,没有作其余任何事情。那么,为了能实现咱们须要的渲染和其余逻辑,就须要了解 Weex Componet 的生命周期。这里的生命周期,实质就是了解可 Override 的几个 WXComponent 方法,和他们的被调用的时机。这一块官方没有任何文档,全靠去 github 源码中看和试。component
protected T initComponentHostView(@NonNull Context context) { // for example mComponentHostView = new FrameLayout(context); mComponentHostView.setId(R.id.fragment_content); return mComponentHostView; }
用于生成根 View 返回给 Weex 来渲染。注意,不要在这里进行任何响应外界设入的 props 的渲染,由于此时极大可能 props 尚未被传入。
@Override public void bindData(WXComponent component) { super.bindData(component); // 这里进行 props 的响应渲染 }
super.bindData() 后便可响应 props 进行渲染,由于此时 props 的set方法都已经被调用过。
@JSMethod @Override public void destroy() { super.destroy(); // 进行自定义 Component 的必要销毁逻辑 }
若是有额外须要销毁的逻辑,须要写在 destroy 之中。weex 会在退出 WXActivity 或其余等同的时候调用。值得一提的是,我通常加一个 @JSMethod 注解,以提供前端 Weex 开发一个主动销毁的能力,避免须要的时候不能及时推代码生效,而要等到发版。
上段其实已经提到,怎样暴露一个 Component 方法给前端调用。以下所示:
@JSMethod public void getDuration(JSCallback callback) { if (null != getCurrentShortVideoVh() && null != callback) { Map<String, Object> map = new HashMap<>(1); map.put("result", "value"); callback.invoke(map); } }
须要注意的是,直接把 void 改为返回值好比 boolean 而后试图 return 是没有用的,weex js 侧收不到。所以,必需要去使用回调来给返回值。如上所示。
Weex 新内核(WeexCore)将 Dom 层和 Layout 引擎下沉到 C++ 层实现,移除 Java 层的 DomObject,提高渲染性能和内核的可通用性。所以,github 最新版再也不能够获取到 WXComponent 中的 DomObject。
若是发现自定义 Component 的逻辑须要用到 Activity,而 WXComponent 只给你提供了 Context 的时候,不要慌,Weex 传入的 Context 其实能够强转 Activity。固然,以防万一,记得用 instance of 保护一下。
同理,若是你想要弹出一个 Fragment,结果发现本身须要一个 FragmentActivity 来getSupportFragmentManager(),不要慌,weex 传入的这个 Activity 也能够强转为FragmentActivity,一样记得加 instance of 保护,不然业务挂了不算个人,由于这毕竟是文档中的未定义行为。