1. 程式人生 > >[腦洞]複雜頁面構建方法

[腦洞]複雜頁面構建方法

問題

每個App都不可避免有一兩個複雜的頁面,首頁啦、主要功能的detail頁啦都跑不掉又臭又長。而當海外成為理所應當拓展的市場時,解耦複雜頁面、在頁面中按需加入功能就是一個剛需了。
具體來說,解耦有幾個方面:介面/功能的解耦、View層面(特別是id)的解耦、生命週期傳遞。

通用解決

  • 對於介面和功能,使用IOC或者Event方式。每個業務有自己的api module(宣告介面和Event,一直打入App)和biz module(實現介面和具體業務邏輯,按需打入)
  • 對於生命週期,方便就用fragment,不方便就用FragmentLifecycleCallbacks

基於RecyclerView的情況

如果是基於RecyclerView的複雜頁面,而且插拔粒度是item級別,那麼僅需要一系列ViewHolder工廠類。

public interface ViewHolderFactory<T> {
  boolean canHandle(T model);
  ViewHolder create(T model);
}

作為mediator的Adapter(module:core)負責:

  • 持有所有可用Factory例項(可用通過註冊去掉core對於biz的依賴)
  • 匹配資料極其對應的Factory例項
  • 路由onCreateViewHolder,當然這時ViewHolder肯定是要有必要的統一的繫結介面

上面這種情況,並沒有什麼太大的問題,因為:

  • View直接的互動為0,不存在id的依賴
  • 所有的介面都可以簡化為ViewHolder+Factory

真正的問題

真正的問題是複雜的Linear頁面,這時,沒有現成的mediator做View管理,比較棘手。

仿照RecyclerView

適合有固定坑位的頁面,比如說股票詳情頁,頁面大概由固定大小的幾部分構成。那麼,可以為每個坑位定義一個ViewType。
不同的使用方宣告好ViewType到xml的對映,直接用List<ViewType>+ Adapter方式做頁面的排布。如果有生命週期強需求,可以直接返回一個Fragment(反正什麼ViewHolder都是自己做主)。
這時候module的依賴是:使用方-> biz … -> core。按需打入的方案是寫死到使用方module中,每個使用方明確整體佈局和所需biz。
優點是直觀、簡單
缺點就是會出現同一個佈局(坑位)重複定義,打包不夠靈活(每個不同使用方都有固定的功能)

改進一點點

可以在core中佈置好所有坑位,每個使用方只是一個配置檔案,如果沒有打入某個biz,其坑位直接GONE掉。
優點是更加簡單,單點修改
缺點是core中佔坑佈局難於維護,頁面結構不夠用靈活(所有需求方都長得一樣)

基於Fragment

很多頁面並沒有預知的固定坑位,比如直播頁面,View似乎是隨性擺到頁面上的。
這時可以使用一個ConstraintLayout(match_parent的)作為Fragment的container,所有的biz module都宣告一個FragmentFactory,mediator負責將fragment加入到container中(add)。所有View、id都放到各自api module中,由此各業務可以自由相互依賴。
View的依賴由每個Fragment在onActivityCreated中加上依賴。
優點是自由度大
缺點是佈局複雜,相當於有一個Canvas,大家隨便畫,容易出現業務之間相互覆蓋的情況

試圖解決大Canvas問題

其實就是在解決ViewGroup layoutChindren時面臨的問題,方法也可以是類似的。讓每個module有自己的大小、位置、優先順序等屬性,mediator 對其進行layout,如果遇到衝突,優先排列優先順序高的module。