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 保護,不然業務掛了不算個人,由於這畢竟是文檔中的未定義行爲。