本文将结合本身的项目开发实践,简单分享一下关于多状态 Layout 的开发实践 Tips。html
我的主页 咕咚java
博文地址: loading_layout_practiceandroid
对于大多数 App 而言,项目中都有多状态加载 View 这种需求,以下图所示。git
对应到开发中,咱们一般会开发一个对应的自定义 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。具体这种方式的实现能够参看一个开源项目 的实现。性能
考虑到 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 类型,一种是加载中的 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 加载提示框架大都和产品设计强相关,不具有通常的通用性。
下面列举一些本身收集到的多状态加载开源方案,方便对比。
一样功能的 Layout 可能在不一样的业务场景下实现方式也会有很大的区别,因此不论哪一种实现方式,无所谓好坏,只要适合就好。可是开发此类 Layout 要遵循的基本准则、以及要注意的点应该大都相同,但愿此文能够给你一些启示帮助。