Android-多狀態加載佈局的開發-Tips

本文將結合本身的項目開發實踐,簡單分享一下關於多狀態 Layout 的開發實踐 Tips。html

我的主頁 咕咚java

博文地址: loading_layout_practiceandroid

什麼是多狀態 Layout

對於大多數 App 而言,項目中都有多狀態加載 View 這種需求,以下圖所示。git

demo

對應到開發中,咱們一般會開發一個對應的自定義 layout 用於根據頁面不一樣的狀態來顯示不一樣的提示 view。github

在項目中,咱們大多會在開發初期就把這套 layout 框架寫好,而後其餘人的本身的開發過程當中直接使用便可。以下所示:性能優化

<name.gudong.MJMultipleStatusLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/lv_activity_center"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</name.gudong.MJMultipleStatusLayout>
複製代碼

這篇文章不討論如何去實現這樣的自定義 loading layout,Github 上這樣的 layout 太多了,這裏主要思考、總結在實際開發中開發這樣的自定義 Layout 時應該注意那些地方。框架

可是爲了說明方便,這裏仍是採用的方案簡單敘述一下。(爲了後文描述方便,這裏把這個多狀態自定義 Layout 先稱爲 MultipleStatusLayout。)工具

實現方案

在實現 MultipleStatusLayout 時,首先選擇繼承一個 ViewGroup 做爲本身的父類,而後默認把內部的第一個子 View 做爲 ContentView,其它各類情形下對應要顯示的 layout view,根據不一樣的加載狀態,在 MultipleStatusLayout 中經過動態 addView 去控制對應 layout 的加載顯示,也能夠經過 ViewStub 把不一樣情形的 layout 進行懶加載,而後對外提供不一樣的方法,方便外部調用、控制不一樣狀態下的 layout 顯示。佈局

嗯,簡單說來就是這樣,原理很簡單,實現起來也沒什麼技術難度,對於通常的開發人員只要一開始明白具體的產品邏輯和實現思路,相信花不了多少時間就能夠完成這樣的 MultipleStatusLayout。具體這種方式的實現能夠參看一個開源項目 的實現。性能

Tips

考慮到 MultipleStatusLayout 開發完成後,會在項目中的不少頁面中應用,並且不少時候是做爲頁面頂級父容器而存在,因此開發過程當中必定要注意其性能還有穩定性,不然一旦出現問題,整個項目中應用到該 MultipleStatusLayout 的頁面都會隨之出現問題。

如下就從性能角度、可維護性、穩定性等方面考慮出發,列舉一些開發 tips。

選擇最合理的父容器

首先 FrameLayout、RelativeLayout、LinearLayout 均可以做爲 MultipleStatusLayout 的父類,拋開如今的應用場景不談,都知道 RelativeLayout 在 layout 時須要 measure 兩次,因此對於一個將來要在不少頁面中使用的 Layout ,把 RelativeLayout 做爲父類這個方案首先 pass 掉。

這裏關於 RelativeLayout 多說兩句,儘管在內部 layout 時它會執行兩次 measure 可是也不能說 RelativeLayout 有性能問題,不然 Android Studio 的 activity 生成模板中也不會使用 RelativeLayout 做爲默認根佈局(AndroidStudio3.0 以前),Google 使用 RelativeLayout 做爲模板默認佈局容器應該是考慮到 RelativeLayout 的另外一個優勢:使用 RelativeLayout 能夠有效下降佈局嵌套的深度。若是作過佈局優化的話,你們應該知道佈局層次越深,layout 性能就越差,官方的性能優化建議也是讓佈局結構寬而淺,而不是窄而深,因此這裏默認設置爲 RelativeLayout 根佈局是有道理的。

可是由於 MultipleStatusLayout 中顯示的 view 大都須要居中顯示,因此使用 RelativeLayout 相對比較容易控制居中位置,這多是不少人選擇 RelativeLayout 做爲父類的初衷。這裏本身能夠作一下權衡。

關於 LinearLayout 和 FrameLayout,若是按照上一節提到的實現方案,其實均可以採用,不過考慮到該類 Layout 的應用場景,建議選擇 FrameLayout。

由於MultipleStatusLayout 將來在大多數狀況下是做爲頁面父容器存在的,既然是父容器,內容可能會有各類變化,這時使用 LinearLayout 這種線性佈局就會在佈局時顯得特別侷限,好比一些頁面可能須要在 MultipleStatusLayout 之上顯示一個 FloatActionButton 或者其餘的 view,這時使用 FrameLayout 就會好作不少也會靈活不少。

選擇最優的加載 View 方式

如何控制這些多狀態對應的 View ? 對於通常的情形,至少有兩種 View 類型,一種是加載中的 loading 樣式 view,一種是異常狀態的 layout view,固然還可能有更多具體的情形。

不一樣的樣式對應一個不一樣的佈局,爲了簡便咱們能夠一次性的把全部狀態對應的佈局都寫在一個 layout 佈局裏,而後能夠經過控制隱藏、顯示來根據不一樣的狀態來展現不一樣 view,這是最直接的想法。

可是,只要多思考一步,就會發現這種方式很是不可取。由於不少時候,MultipleStatusLayout 做爲一個父容器只關心本身的 ContentView,異常頁面和加載頁面甚至可能沒有機會出現,可是如今這樣作就表示,這個頁面不論有沒有異常或者加載邏輯,你的佈局裏都會存在對應的 layout 佈局代碼。這樣在界面繪製時就會白白耗掉多餘的時間。

並且這個 Layout 後續會在項目不少頁面用到,因此這裏的佈局耗時問題放大後就顯得很嚴重。

鑑於此,取而代之的更好的作法應該是動態去 addView,只有這個頁面第一次調用 loading 或者 showError 這樣的方法,我纔去把對應佈局加載進來,固然這裏使用 ViewStub 也是同樣的效果。

這裏也就是說,只有調用了相應的方法,纔去加載對應的 layout.

資源命名

其實這個問題是本身開發公用 Api 廣泛面臨的問題,因爲開發 MultipleStatusLayout 可能會定義一些顏色資源或者背景資源,這裏建議全部資源開頭使用一個固定的開頭,這樣能夠防止跟主版本中的資源重名。進而早成一些奇怪的 UI 問題或者編譯問題。好比按鈕的背景你能夠定義爲 msl_btn_normal 而不是 btn_normal,文字的顏色你能夠定義爲 msl_text_white 而不是 text_white。這樣就能夠有效避免一些資源衝突。

更多關於如何開發一個第三方庫,能夠查看天之界線開發第三方庫最佳實踐

提供友好的方法調用方式

既然是提供給你們使用,你就應該在方法命名上多花點心思,最好見名之意,這樣你們調用時也會舒服不少。

另外對外提供 Api 時也應該保持克制。不要一會兒提供出去太多的方法,不論有用沒用,一會兒都對外提供,這樣會對後續的維護形成隱形的負擔,由於提供的公用方法越多,表示你後續都要對這些方法進行維護。

最好的原則就是用到什麼提供什麼,不要提早設計。

另外,隨着項目迭代,對外提供方法的參數可能會變得多起來,好比之前顯示錯誤頁面的方法是

void showErrorView(Stirng error) 複製代碼

後來要增長自定義的 icon 或者點擊事件響應,這時你就須要擴展方法參數,每每這種參數可能會變得不少不可收拾,這時建議使用 Build 構建模式設計,以下示例所示:

showErrorView(StatusViewConfig config) 
複製代碼

調用時就能夠這樣調用

showErrorView(new StatusViewConfig.StatusViewBuild(getContext())
                .icon(icon)
                .message(message)
                .subMessage(subMessage)
                .layoutMode(mLayoutMode)
                .withActionText(actionText, clickListener)
                .build())
複製代碼

良好的文檔

當你開發完成後,最好趁熱寫一份簡單明瞭的使用文檔出來,這樣你們就能夠直接對照文檔使用你寫的庫,不用去關心代碼實現,直接調用 Api 就能夠完成本身的業務需求,同時也省的本身去面對面跟別人講怎麼使用了。

前段時間在 V 站上看到一個問題,說大家公司使用什麼樣的文檔管理工具?其中有一個回答言簡意賅,頗有意思,四個字 口口相傳

其實對於任何一個項目都是,有時間寫點文檔,梳理本身思路的同時方便別人,何樂而不爲。

其餘

這種 Layout 在項目中會隨着項目的更新迭代而不斷的更新,因此一開始你就應該知道,後續還要不斷迭代更新,因此代碼設計實現時應該留意擴展性。

另外,相關的開源方案有不少,建議一開始能夠參考一些好的方案,而後結合本身項目的實際需求,來開發維護屬於本身項目的一套框架。由於多狀態 loading 加載提示框架大都和產品設計強相關,不具有通常的通用性。

下面列舉一些本身收集到的多狀態加載開源方案,方便對比。

開源方案

StatefulLayout

progress-activity

StateLayout

MultipleStatusView

總結

一樣功能的 Layout 可能在不一樣的業務場景下實現方式也會有很大的區別,因此不論哪一種實現方式,無所謂好壞,只要適合就好。可是開發此類 Layout 要遵循的基本準則、以及要注意的點應該大都相同,但願此文能夠給你一些啓示幫助。

關注我

相關文章
相關標籤/搜索