作者博客地址: http://gudong.name
本文博客地址: http://gudong.name/2017/04/26/loading_layout_practice.html
本文將結(jié)合自己的項目開發(fā)實踐弹沽,簡單分享一下關(guān)于多狀態(tài) Layout 的開發(fā)實踐 Tips。
什么是多狀態(tài) Layout
對于大多數(shù) App 而言履腋,項目中都有多狀態(tài)加載 View 這種需求欧漱,如下圖所示砰嘁。
對應(yīng)到開發(fā)中污桦,我們通常會開發(fā)一個對應(yīng)的自定義 layout 用于根據(jù)頁面不同的狀態(tài)來顯示不同的提示 view。
在項目中秋泄,我們大多會在開發(fā)初期就把這套 layout 框架寫好阱持,然后其他人的自己的開發(fā)過程中直接使用即可夭拌。如下所示:
<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>
這篇文章不討論如何去實現(xiàn)這樣的自定義 loading layout,Github 上這樣的 layout 太多了衷咽,這里主要思考鸽扁、總結(jié)在實際開發(fā)中開發(fā)這樣的自定義 Layout 時應(yīng)該注意那些地方。
但是為了說明方便镶骗,這里還是采用的方案簡單敘述一下桶现。
為了后文描述方便,這里把這個多狀態(tài)自定義 Layout 先稱為 MultipleStatusLayout鼎姊。
實現(xiàn)方案
在實現(xiàn) MultipleStatusLayout 時骡和,首先選擇繼承一個 ViewGroup 作為自己的父類,然后默認(rèn)把內(nèi)部的第一個子 View 作為 ContentView相寇,其它各種情形下對應(yīng)要顯示的 layout view慰于,根據(jù)不同的加載狀態(tài),在 MultipleStatusLayout 中通過動態(tài) addView 去控制對應(yīng) layout 的加載顯示唤衫,也可以通過 ViewStub 把不同情形的 layout 進行懶加載婆赠,然后對外提供不同的方法,方便外部調(diào)用佳励、控制不同狀態(tài)下的 layout 顯示休里。
嗯蛆挫,簡單說來就是這樣,原理很簡單妙黍,實現(xiàn)起來也沒什么技術(shù)難度悴侵,對于一般的開發(fā)人員只要一開始明白具體的產(chǎn)品邏輯和實現(xiàn)思路,相信花不了多少時間就可以完成這樣的 MultipleStatusLayout拭嫁。具體這種方式的實現(xiàn)可以參看一個開源項目 的實現(xiàn)畜挨。
下面著重列舉一下開發(fā) MultipleStatusLayout 過程中的注意點或者要點。
Tips
考慮到 MultipleStatusLayout 開發(fā)完成后噩凹,會在項目中的很多頁面中應(yīng)用,而且很多時候是作為頁面頂級父容器而存在毡咏,所以開發(fā)過程中一定要注意其性能還有穩(wěn)定性驮宴,否則一旦出現(xiàn)問題,整個項目中應(yīng)用到該 MultipleStatusLayout 的頁面都會隨之出現(xiàn)問題呕缭。
以下就從性能角度、可維護性、穩(wěn)定性等方面考慮出發(fā)闰靴,列舉一些開發(fā) tip 巢掺。
選擇最合理的父容器
首先 FrameLayout、RelativeLayout片仿、LinearLayout 都可以作為 MultipleStatusLayout 的父類纹安,拋開現(xiàn)在的應(yīng)用場景不談,都知道 RelativeLayout 在 layout 時需要 measure 兩次砂豌,所以對于一個未來要在很多頁面中使用的 Layout 厢岂,把 RelativeLayout 作為父類這個方案首先 pass 掉。
但是因為 MultipleStatusLayout 中顯示的 view 大都需要居中顯示阳距,所以使用 RelativeLayout 相對比較容易控制居中位置塔粒,這可能是很多人選擇 RelativeLayout 作為父類的初衷。這里自己可以做一下權(quán)衡筐摘。
關(guān)于 LinearLayout 和 FrameLayout卒茬,如果按照上一節(jié)提到的實現(xiàn)方案,其實都可以采用咖熟,不過考慮到該類 Layout 的應(yīng)用場景圃酵,建議選擇 FrameLayout。
因為MultipleStatusLayout 未來在大多數(shù)情況下是作為頁面父容器存在的馍管,既然是父容器辜昵,內(nèi)容可能會有各種變化咽斧,這時使用 LinearLayout 這種線性布局就會在布局時顯得特別局限堪置,比如一些頁面可能需要在 MultipleStatusLayout 之上顯示一個 FloatActionButton 或者其他的 view躬存,這時使用 FrameLayout 就會好做很多也會靈活很多。
選擇最優(yōu)的加載 View 方式
如何控制這些多狀態(tài)對應(yīng)的 View ? 對于一般的情形舀锨,至少有兩種 View 類型岭洲,一種是加載中的 loading 樣式 view,一種是異常狀態(tài)的 layout view坎匿,當(dāng)然還可能有更多具體的情形盾剩。
不同的樣式對應(yīng)一個不同的布局,為了簡便我們可以一次性的把所有狀態(tài)對應(yīng)的布局都寫在一個 layout 布局里替蔬,然后可以通過控制隱藏告私、顯示來根據(jù)不同的狀態(tài)來展示不同 view,這是最直接的想法承桥。
但是驻粟,只要多思考一步,就會發(fā)現(xiàn)這種方式非常不可取凶异。因為很多時候蜀撑,MultipleStatusLayout 作為一個父容器只關(guān)心自己的 ContentView,異常頁面和加載頁面甚至可能沒有機會出現(xiàn)剩彬,但是現(xiàn)在這樣做就表示酷麦,這個頁面不論有沒有異常或者加載邏輯喉恋,你的布局里都會存在對應(yīng)的 layout 布局代碼沃饶。這樣在界面繪制時就會白白耗掉多余的時間。
而且這個 Layout 后續(xù)會在項目很多頁面用到轻黑,所以這里的布局耗時問題放大后就顯得很嚴(yán)重绍坝。
鑒于此,取而代之的更好的做法應(yīng)該是動態(tài)去 addView苔悦,只有這個頁面第一次調(diào)用 loading 或者 showError 這樣的方法轩褐,我才去把對應(yīng)布局加載進來,當(dāng)然這里使用 ViewStub 也是一樣的效果玖详。
這里也就是說把介,只有調(diào)用了相應(yīng)的方法,才去加載對應(yīng)的 layout.
資源命名
其實這個問題是自己開發(fā)公用 Api 普遍面臨的問題蟋座,由于開發(fā) MultipleStatusLayout 可能會定義一些顏色資源或者背景資源拗踢,這里建議所有資源開頭使用一個固定的開頭,這樣可以防止跟主版本中的資源重名向臀。進而早成一些奇怪的 UI 問題或者編譯問題巢墅。比如按鈕的背景你可以定義為 msl_btn_normal 而不是 btn_normal,文字的顏色你可以定義為 msl_text_white 而不是 text_white。這樣就可以有效避免一些資源沖突君纫。
更多關(guān)于如何開發(fā)一個第三方庫驯遇,可以查看天之界線的開發(fā)第三方庫最佳實踐
提供友好的方法調(diào)用方式
既然是提供給大家使用,你就應(yīng)該在方法命名上多花點心思蓄髓,最好見名之意叉庐,這樣大家調(diào)用時也會舒服很多。
另外對外提供 Api 時也應(yīng)該保持克制会喝。不要一下子提供出去太多的方法陡叠,不論有用沒用,一下子都對外提供肢执,這樣會對后續(xù)的維護造成隱形的負擔(dān)枉阵,因為提供的公用方法越多,表示你后續(xù)都要對這些方法進行維護预茄。
最好的原則就是用到什么提供什么兴溜,不要提前設(shè)計。
另外反璃,隨著項目迭代,對外提供方法的參數(shù)可能會變得多起來假夺,比如以前顯示錯誤頁面的方法是
void showErrorView(Stirng error)
后來要增加自定義的 icon 或者點擊事件響應(yīng)淮蜈,這時你就需要擴展方法參數(shù),往往這種參數(shù)可能會變得很多不可收拾已卷,這時建議使用 Build 構(gòu)建模式設(shè)計梧田,如下示例所示:
showErrorView(StatusViewConfig config)
調(diào)用時就可以這樣調(diào)用
showErrorView(new StatusViewConfig.StatusViewBuild(getContext())
.icon(icon)
.message(message)
.subMessage(subMessage)
.layoutMode(mLayoutMode)
.withActionText(actionText, clickListener)
.build())
良好的文檔
當(dāng)你開發(fā)完成后,最好趁熱寫一份簡單明了的使用文檔出來侧蘸,這樣大家就可以直接對照文檔使用你寫的庫裁眯,不用去關(guān)心代碼實現(xiàn),直接調(diào)用 Api 就可以完成自己的業(yè)務(wù)需求讳癌,同時也省的自己去面對面跟別人講怎么使用了穿稳。
前段時間在 V 站上看到一個問題,說你們公司使用什么樣的文檔管理工具晌坤?其中有一個回答言簡意賅逢艘,很有意思,四個字 口口相傳
骤菠。
其實對于任何一個項目都是它改,有時間寫點文檔,梳理自己思路的同時方便別人商乎,何樂而不為央拖。
其他
這種 Layout 在項目中會隨著項目的更新迭代而不斷的更新,所以一開始你就應(yīng)該知道,后續(xù)還要不斷迭代更新鲜戒,所以代碼設(shè)計實現(xiàn)時應(yīng)該留意擴展性专控。
另外,相關(guān)的開源方案有很多袍啡,建議一開始可以參考一些好的方案踩官,然后結(jié)合自己項目的實際需求,來開發(fā)維護屬于自己項目的一套框架境输。因為多狀態(tài) loading 加載提示框架大都和產(chǎn)品設(shè)計強相關(guān)蔗牡,不具備一般的通用性。
下面列舉一些自己收集到的多狀態(tài)加載開源方案嗅剖,方便對比辩越。
開源方案
總結(jié)
同樣功能的 Layout 可能在不同的業(yè)務(wù)場景下實現(xiàn)方式也會有很大的區(qū)別,所以不論哪種實現(xiàn)方式信粮,無所謂好壞黔攒,只要適合就好。但是開發(fā)此類 Layout 要遵循的基本準(zhǔn)則强缘、以及要注意的點應(yīng)該大都相同督惰,希望此文可以給你一些啟示幫助。
本文原創(chuàng)發(fā)布于公眾號 大俠咕咚旅掂,歡迎掃碼關(guān)注更多原創(chuàng)文章赏胚。
大俠咕咚