Android 多状态加载布局的开发 Tips
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
什么是多狀態(tài) Layout
對(duì)于大多數(shù) App 而言,項(xiàng)目中都有多狀態(tài)加載 View 這種需求,如下圖所示。
對(duì)應(yīng)到開發(fā)中,我們通常會(huì)開發(fā)一個(gè)對(duì)應(yīng)的自定義 layout 用于根據(jù)頁面不同的狀態(tài)來顯示不同的提示 view。
在項(xiàng)目中,我們大多會(huì)在開發(fā)初期就把這套 layout 框架寫好,然后其他人的自己的開發(fā)過程中直接使用即可。如下所示:
<name.gudong.MJMultipleStatusLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><ListViewandroid:id="@+id/lv_activity_center"android:layout_width="match_parent"android:layout_height="match_parent" /></name.gudong.MJMultipleStatusLayout>這篇文章不討論如何去實(shí)現(xiàn)這樣的自定義 loading layout,Github 上這樣的 layout?太多了,這里主要思考、總結(jié)在實(shí)際開發(fā)中開發(fā)這樣的自定義 Layout 時(shí)應(yīng)該注意那些地方。
但是為了說明方便,這里還是采用的方案簡單敘述一下。
為了后文描述方便,這里把這個(gè)多狀態(tài)自定義 Layout 先稱為 MultipleStatusLayout。
實(shí)現(xiàn)方案
在實(shí)現(xiàn) MultipleStatusLayout 時(shí),首先選擇繼承一個(gè) ViewGroup 作為自己的父類,然后默認(rèn)把內(nèi)部的第一個(gè)子 View 作為 ContentView,其它各種情形下對(duì)應(yīng)要顯示的 layout view,根據(jù)不同的加載狀態(tài),在 MultipleStatusLayout 中通過動(dòng)態(tài) addView 去控制對(duì)應(yīng) layout 的加載顯示,也可以通過 ViewStub 把不同情形的 layout 進(jìn)行懶加載,然后對(duì)外提供不同的方法,方便外部調(diào)用、控制不同狀態(tài)下的 layout 顯示。
嗯,簡單說來就是這樣,原理很簡單,實(shí)現(xiàn)起來也沒什么技術(shù)難度,對(duì)于一般的開發(fā)人員只要一開始明白具體的產(chǎn)品邏輯和實(shí)現(xiàn)思路,相信花不了多少時(shí)間就可以完成這樣的 MultipleStatusLayout。具體這種方式的實(shí)現(xiàn)可以參看一個(gè)開源項(xiàng)目?的實(shí)現(xiàn)。
下面著重列舉一下開發(fā) MultipleStatusLayout 過程中的注意點(diǎn)或者要點(diǎn)。
Tips
考慮到 MultipleStatusLayout 開發(fā)完成后,會(huì)在項(xiàng)目中的很多頁面中應(yīng)用,而且很多時(shí)候是作為頁面頂級(jí)父容器而存在,所以開發(fā)過程中一定要注意其性能還有穩(wěn)定性,否則一旦出現(xiàn)問題,整個(gè)項(xiàng)目中應(yīng)用到該 MultipleStatusLayout 的頁面都會(huì)隨之出現(xiàn)問題。
以下就從性能角度、可維護(hù)性、穩(wěn)定性等方面考慮出發(fā),列舉一些開發(fā) tip 。
選擇最合理的父容器
首先 FrameLayout、RelativeLayout、LinearLayout 都可以作為 MultipleStatusLayout 的父類,拋開現(xiàn)在的應(yīng)用場景不談,都知道 RelativeLayout 在 layout 時(shí)需要 measure 兩次,所以對(duì)于一個(gè)未來要在很多頁面中使用的 Layout ,把 RelativeLayout 作為父類這個(gè)方案首先 pass 掉。
但是因?yàn)?MultipleStatusLayout 中顯示的 view 大都需要居中顯示,所以使用 RelativeLayout 相對(duì)比較容易控制居中位置,這可能是很多人選擇 RelativeLayout 作為父類的初衷。這里自己可以做一下權(quán)衡。
關(guān)于 LinearLayout 和 FrameLayout,如果按照上一節(jié)提到的實(shí)現(xiàn)方案,其實(shí)都可以采用,不過考慮到該類 Layout 的應(yīng)用場景,建議選擇 FrameLayout。
因?yàn)镸ultipleStatusLayout 未來在大多數(shù)情況下是作為頁面父容器存在的,既然是父容器,內(nèi)容可能會(huì)有各種變化,這時(shí)使用 LinearLayout 這種線性布局就會(huì)在布局時(shí)顯得特別局限,比如一些頁面可能需要在 MultipleStatusLayout 之上顯示一個(gè) FloatActionButton 或者其他的 view,這時(shí)使用 FrameLayout 就會(huì)好做很多也會(huì)靈活很多。
選擇最優(yōu)的加載 View 方式
如何控制這些多狀態(tài)對(duì)應(yīng)的 View ? 對(duì)于一般的情形,至少有兩種 View 類型,一種是加載中的 loading 樣式 view,一種是異常狀態(tài)的 layout view,當(dāng)然還可能有更多具體的情形。
不同的樣式對(duì)應(yīng)一個(gè)不同的布局,為了簡便我們可以一次性的把所有狀態(tài)對(duì)應(yīng)的布局都寫在一個(gè) layout 布局里,然后可以通過控制隱藏、顯示來根據(jù)不同的狀態(tài)來展示不同 view,這是最直接的想法。
但是,只要多思考一步,就會(huì)發(fā)現(xiàn)這種方式非常不可取。因?yàn)楹芏鄷r(shí)候,MultipleStatusLayout 作為一個(gè)父容器只關(guān)心自己的 ContentView,異常頁面和加載頁面甚至可能沒有機(jī)會(huì)出現(xiàn),但是現(xiàn)在這樣做就表示,這個(gè)頁面不論有沒有異常或者加載邏輯,你的布局里都會(huì)存在對(duì)應(yīng)的 layout 布局代碼。這樣在界面繪制時(shí)就會(huì)白白耗掉多余的時(shí)間。
而且這個(gè) Layout 后續(xù)會(huì)在項(xiàng)目很多頁面用到,所以這里的布局耗時(shí)問題放大后就顯得很嚴(yán)重。
鑒于此,取而代之的更好的做法應(yīng)該是動(dòng)態(tài)去 addView,只有這個(gè)頁面第一次調(diào)用 loading 或者 showError 這樣的方法,我才去把對(duì)應(yīng)布局加載進(jìn)來,當(dāng)然這里使用 ViewStub 也是一樣的效果。
這里也就是說,只有調(diào)用了相應(yīng)的方法,才去加載對(duì)應(yīng)的 layout.
資源命名
其實(shí)這個(gè)問題是自己開發(fā)公用 Api 普遍面臨的問題,由于開發(fā) MultipleStatusLayout 可能會(huì)定義一些顏色資源或者背景資源,這里建議所有資源開頭使用一個(gè)固定的開頭,這樣可以防止跟主版本中的資源重名。進(jìn)而早成一些奇怪的 UI 問題或者編譯問題。比如按鈕的背景你可以定義為 msl_btn_normal 而不是 btn_normal,文字的顏色你可以定義為 msl_text_white 而不是 text_white。這樣就可以有效避免一些資源沖突。
更多關(guān)于如何開發(fā)一個(gè)第三方庫,可以查看天之界線的開發(fā)第三方庫最佳實(shí)踐
提供友好的方法調(diào)用方式
既然是提供給大家使用,你就應(yīng)該在方法命名上多花點(diǎn)心思,最好見名之意,這樣大家調(diào)用時(shí)也會(huì)舒服很多。
另外對(duì)外提供 Api 時(shí)也應(yīng)該保持克制。不要一下子提供出去太多的方法,不論有用沒用,一下子都對(duì)外提供,這樣會(huì)對(duì)后續(xù)的維護(hù)造成隱形的負(fù)擔(dān),因?yàn)樘峁┑墓梅椒ㄔ蕉?#xff0c;表示你后續(xù)都要對(duì)這些方法進(jìn)行維護(hù)。
最好的原則就是用到什么提供什么,不要提前設(shè)計(jì)。
另外,隨著項(xiàng)目迭代,對(duì)外提供方法的參數(shù)可能會(huì)變得多起來,比如以前顯示錯(cuò)誤頁面的方法是
void showErrorView(Stirng error)后來要增加自定義的 icon 或者點(diǎn)擊事件響應(yīng),這時(shí)你就需要擴(kuò)展方法參數(shù),往往這種參數(shù)可能會(huì)變得很多不可收拾,這時(shí)建議使用 Build 構(gòu)建模式設(shè)計(jì),如下示例所示:
showErrorView(StatusViewConfig config)調(diào)用時(shí)就可以這樣調(diào)用
showErrorView(new StatusViewConfig.StatusViewBuild(getContext()).icon(icon).message(message).subMessage(subMessage).layoutMode(mLayoutMode).withActionText(actionText, clickListener).build())良好的文檔
當(dāng)你開發(fā)完成后,最好趁熱寫一份簡單明了的使用文檔出來,這樣大家就可以直接對(duì)照文檔使用你寫的庫,不用去關(guān)心代碼實(shí)現(xiàn),直接調(diào)用 Api 就可以完成自己的業(yè)務(wù)需求,同時(shí)也省的自己去面對(duì)面跟別人講怎么使用了。
前段時(shí)間在 V 站上看到一個(gè)問題,說你們公司使用什么樣的文檔管理工具?其中有一個(gè)回答言簡意賅,很有意思,四個(gè)字?口口相傳。
其實(shí)對(duì)于任何一個(gè)項(xiàng)目都是,有時(shí)間寫點(diǎn)文檔,梳理自己思路的同時(shí)方便別人,何樂而不為。
其他
這種 Layout 在項(xiàng)目中會(huì)隨著項(xiàng)目的更新迭代而不斷的更新,所以一開始你就應(yīng)該知道,后續(xù)還要不斷迭代更新,所以代碼設(shè)計(jì)實(shí)現(xiàn)時(shí)應(yīng)該留意擴(kuò)展性。
另外,相關(guān)的開源方案有很多,建議一開始可以參考一些好的方案,然后結(jié)合自己項(xiàng)目的實(shí)際需求,來開發(fā)維護(hù)屬于自己項(xiàng)目的一套框架。因?yàn)槎酄顟B(tài) loading 加載提示框架大都和產(chǎn)品設(shè)計(jì)強(qiáng)相關(guān),不具備一般的通用性。
下面列舉一些自己收集到的多狀態(tài)加載開源方案,方便對(duì)比。
開源方案
StatefulLayout
progress-activity
StateLayout
MultipleStatusView
總結(jié)
同樣功能的 Layout 可能在不同的業(yè)務(wù)場景下實(shí)現(xiàn)方式也會(huì)有很大的區(qū)別,所以不論哪種實(shí)現(xiàn)方式,無所謂好壞,只要適合就好。但是開發(fā)此類 Layout 要遵循的基本準(zhǔn)則、以及要注意的點(diǎn)應(yīng)該大都相同,希望此文可以給你一些啟示幫助。
轉(zhuǎn)載于:https://my.oschina.net/bv10000/blog/891258
總結(jié)
以上是生活随笔為你收集整理的Android 多状态加载布局的开发 Tips的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做梦梦到自己被洪水冲走了是什么意思
- 下一篇: 《Android 应用案例开发大全(第二