做過weex開發的同學應該都知道weex的原生擴充可以分為module擴充和component擴充,component擴充也可以被稱為UI元件擴充,我們把原生中的UI元件封裝之後就能在vue檔案中以标簽的方式使用了,這裡我們主要講一下component的擴充。
正常的component擴充知識在weex官網中都有教程,我在這裡就不再贅述了,如果還不熟悉的話請移步weex官網中的教程。
那麼我們接下來就着重介紹一下官網中沒有提到的部分,分為容器類元件和獨立元件兩個部分探讨,我們以map元件為例進行。
-
獨立元件
initComponentHostView
這個方法我們可以看出是初始化元件宿主view的方法,我們通常會重寫這個方法傳回我們要顯示的原生view,并進行元件一些相關資料的初始化。
@Override
protected WeexMapView initComponentHostView(@NonNull Context context) {
this.mapView = new WeexMapView(context);
if (context instanceof Activity) {
mActivity = (Activity) context;
}
requestPermissions();
return this.mapView;
}
setProperty
這個方法是設定元件屬性的方法,我們可以在合适的時候調用來設定元件的屬性。一般在開發獨立元件的時候不會使用這個方法,因為我們通過在各個屬性的set方法上添加@component注解就可以動态設定其屬性了。但是有時候我們的所設定的屬性不是直接作用在原生view上,而是在一些adapter或者option上配置,設定完成才會設定到原生view上,這個時候為了確定屬性在option上已經配置完成,需要在initComponentHostView方法中周遊屬性調用此方法設定,簡單示例如下:
@Override
protected View initComponentHostView(@NonNull Context context) {
view= new View();
options=new Options();
for (String key:getAttrs().keySet()){
setProperty(key,getAttrs().get(key));
}
return view;
}
onHostViewInitialized
這個方法是元件的原生view初始化完成時候會回調的方法,我們在這裡可以做一些需要的處理。比如在option參數設定完成後再此方法中我們可以将option設定到view上。
/*初始化完成回調,在setProperty設定完所有屬性後在這裡進行設定*/
@Override
protected void onHostViewInitialized(View host) {
super.onHostViewInitialized(host);
view.setOption(option);
}
@JSMethod(uiThread = true)
我們如果需要在vue的js代碼中調用原生元件的方法我們需要在方法上添加@JSMethod注解将方法暴露給js,
@JSMethod(uiThread = true)
/*地圖縮放到指定比例大小*/
public void setZoomTo(int zoom){
mapView.aMap.moveCamera(CameraUpdateFactory.zoomTo(zoom));
}
在js中調用方法如下
<map ref="map"></map>
this.$refs.map.setZoomTo(10);
-
容器類元件
父元件: 繼承WXVContainer類
initComponentHostView(@NonNull Context context)
與獨立元件中用法相同。
createChildViewAt(int index)
通常在需要區分子元件類型時使用,最終會調用addSubView方法。我們需要注意的是在重寫此方法是不能将其父類中的child.createView()這行代碼,否則就不會再調用子元件的構造方法之外的其他方法了。
//WXComponet源碼
public void createChildViewAt(int index) {
Pair<WXComponent, Integer> ret = rearrangeIndexAndGetChild(index);
if (ret.first != null) {
WXComponent child = ret.first;
//這行代碼不要覆寫
child.createView();
//下面的代碼可以按照自己的需求進行修改
if (!child.isVirtualComponent()) {
addSubView(child.getHostView(), ret.second);
}
}
}
addSubView(View child, int index)
子元件添加或者設定到到父元件中,比如要自定義ListView子元件,我們就可以在這裡講view添加到資料集合中,并調用Adapter的notifyDataSetChanged重新整理ListView。
//添加子元素時回調
@Override
public void addSubView(View child, int index) {
weexPages.add(child);
adapter.notifyDataSetChanged();
if(index==getChildCount()-1){
hostView.setCurrentItem(position);
}
}
remove(WXComponent child, boolean destroy)
子元件被移除時做一些必要的處理
//移除子元素時回調
@Override
public void remove(WXComponent child, boolean destroy) {
weexPages.remove(child.getHostView());
adapter.notifyDataSetChanged();
}
子元件:
initComponentHostView(@NonNull Context context)
通過實踐發現在自定義容器類元件中使用自定義的子元件時其屬性無法僅僅通過@component注解動态更新;并且子元件如果不需要傳回真實的view,而是作為元件(vue标簽)的形式調用父元件的方法最後傳回父類的initComponentHostView即可。
@Override
protected View initComponentHostView(@NonNull Context context) {
mapView = (WeexMapView) getParent().getRealView();
addMarkerListener();
options=new MarkerOptions();
//自定義容器類元件的子元件需要在初始化是周遊屬性進行屬性設定
for (String key:getAttrs().keySet()){
setProperty(key,getAttrs().get(key));
}
//這裡如果此元件最終目的是調用父元件方法則傳回父類的初始化方法
return super.initComponentHostView(context);
}
updateAttrs(Map attrs)
通過實踐發現在自定義容器類元件中使用自定義的子元件時其屬性無法僅僅通過@component注解動态更新,是以我們需要在此方法中監聽屬性的變化進行屬性的設定。此回調方法中的Map參數傳回的就是發生變化的屬性的集合。
@Override
public void updateAttrs(Map attrs) {
super.updateAttrs(attrs);
for (Object key:attrs.keySet()){
setProperty(key.toString(),attrs.get(key));
}
//在這裡重新設定元件參數
addMarker();
}
onHostViewInitialized(WeexMapView host)
在這裡講虛拟元件設定到父元件上
以上就是我對weex開發Android元件在實踐中的了解和總結,如果有不對的地方還望不吝告知。另外我的開源的weex快速開發的開源項目https://liuxinyea.github.io/IWeex/,有一些自己擴充的component和module,各位同學如果感興趣可以看一下。