Android布局优化,分界面多情状加载

需求

在档案的次序支付的历程中,要求对Api的数据的例外情况反映到UI分界面上,以完成卓绝的顾客体验,Api的数目标场地大约可分为异步央浼数据、不荒谬再次来到数据、空数据、加载退步、互连网错误等局地意况,相应的布局意况也可分为加载中、符合规律展现、无数据、加载出错等景色,于是就有了对多情况布局举行保管的需要。

在最早那些必要刚被提出来的时候,最最早的做法是利用FrameLayout或LinearLayout布局里面嵌套对应状态的xml布局,在各类境况布局切换时,须要在Activity或Fragment里使用java代码频仍的调用各样view的突显与遮蔽,最终那样做出来形成代码臃肿,操作繁琐,何况不可复用,最后只好重构,于是就有了EmptyLayout多状态布局。

根据布局特点、扩大性、品质方面考虑,RelativeLayout由于在 layout 时要求measure 五遍被忽视,LinearLayout也能够视作父布局,不过FrameLayout的层系的特色更符合,举例在空布局状态时索要在最上端展现别的的view的气象下,如下图所示

图片 1empty.jpg

率先为各个布局情状定义标识位

图片 2代码.jpg

随着在 attrs.xml 中定义自定义属性,用于配置在差别情况页的暗中认可属性xml然后在初始化的时候经过 TypedArray 实行赋值

类内部维护一个View的List 的集聚,为畸形布局各定义三个Tag

图片 3代码.jpg

重写FrameLayout的 addView 方法把非平常布局过滤

图片 4代码.jpg

下一场在切换布局时把Tag设置到相应的View,例如`setErrorView

图片 5代码.jpg

谈到底在对外开放叁个接口,提供错误重试的回调

图片 6代码.jpg

那样一来就把各类布局情状的切换操作封装到自定义组合的Layout中了,只要求对外开放api就行了

图片 7代码.jpg

中间的skipId是上航海用体育地方中要求在空数据状态下显得的view的Id的聚合。基于LinearLayout的利用情况比相当多,作者还落到实处了LinearEmptyLayout简版多境况切换的Layout,详细的代码以及萨姆ple能够去笔者的github查看,认为还足以的无妨Star或follow

前言
本篇文章为Android优化的布局地分,该部分应该是Android中很关键的,无论是在自定义控件中,依然在简练的书写布局时,都应有尽量依据一些优化原则,那样布局的绘图效用才会越来越高,体验技能更加好。
一 优化layout的层级
Layout结构假诺太复杂,Android的绘图进度就能很复杂,measure进程就能够很复杂,作者分析的View绘制机制中详尽介绍了百分百度量、布局和制图进程,过于复杂、嵌套的布局会招致质量难题。
1.1 防止嵌套
嵌套的 LinearLayout 恐怕会使得 View 的层级结构很深。使用LinearLayout时,经常大家欣赏用嵌套的布局来动态设置三个View的Visibility ,由于LinearLayout是线性的,由此固然隐形三个View也不会听得多了就能说的清楚到其余View的排列。而在RelativeLayout中,View的岗位都以相对于别的View的,由此,掩饰之后,会形成后边的View未有参谋对象了,导致的周旋地点变动,那时你能够动用alignWithParentIfMissing=”true”来拍卖这种气象。
除此以外,嵌套使用了 layout_weight 参数的 LinearLayout 的计算量会进一步大,因为各种子成分都亟待被度量五回。那对急需多次重复 inflate 的 Layout 极度须求注意,举个例子动用 ListView 或 GridView 时。
1.2 使用merge标签优化层级
在动用了include后恐怕产生布局嵌套过多,出现不供给的layout节点,从而致使剖判变慢。
merge标签可用于二种标准气象:
布局顶结点是FrameLayout且不需要设置background或padding等品质,能够用merge替代,因为Activity内容总括的parent view便是个FrameLayout,所以能够用merge化解只剩二个。
某布局作为子布局被别的布局include时,使用merge当作该布局的顶节点,那样在被引进时顶结点会活动被忽略,而将其子节点全体集结到主布局中。

思考

EmptyLayout尽管已经有了非常多的运用场景,可是就算你的页面是基于RecyclerView写的,本着幸免view嵌套的规格,利用修饰者方式,可感到RecyclerView定义一个EmptyWapper的Adapter,通过Adapter的type调控空页面和谬误页面切换。

举例说,假若您有三个 Layout 是贰个竖直方向的 LinearLayout,当中包含五个一而再的 View 能够在别的 Layout 中选定,那么您会做贰个 LinearLayout 来含有那多个 View ,以便重用。不过,当使用另七个 LinearLayout 来嵌套那么些可选取的 LinearLayout 时,这种嵌套 LinearLayout 的方法除了减慢你的 UI 质量外未有别的意义。
为了避免这种情状,你能够用 元一直庖代可选取 Layout 的根节点。举例:

<merge xmlns:android="http://schemas.android.com/apk/res/android"> 
<Button 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:text="@string/add"
/> 
<Button android:layout_width="fill_parent"    
    android:layout_height="wrap_content"
 android:text="@string/delete"
/></merge>

以往,当您要将以此 Layout 包罗到另叁个 Layout 中时(并且动用了 标签),系统会一向把八个 Button 放到 Layout 中,而不会有剩余的 Layout 被嵌套。

二 使用标签重用Layout

如果你的次第 UI 在不相同地方重复使用有个别Layout,那本节教你什么创制高效的,可选择的 Layout 部件,并把它们“包涵”到 UI Layout 中。
为了快速重用整个的 Layout,你能够使用 和 标签把其余 Layout 嵌入当前 Layout。

三 按需载入视图
除了简单的把三个 Layout 包涵到另贰在那之中,你只怕还想在前后相继开端后,仅当您的 Layout 对客户可知时才初始载入。
3.1 没有要求及时加载的布局,设置为GONE,系统会跳过,不加载
3.2 使用ViewStub 达成按需加载
ViewStub 是三个轻量的视图,无需大小音信,也不会在被参加的 Layout 中绘制任何事物。各种 ViewStub 只供给设置 android:layout 属性来钦定须求被 inflate 的 Layout 类型。viewstub常用来引进那么些私下认可不会显得,只在特种境况下显得的布局,如进程布局、网络战败显示的刷新布局、消息出错出现的晋升布局等。
以下 ViewStub 是一个半透明的进度条覆盖层。作用上讲,它应有只在新的数目项被导入到应用程序时可知。

<ViewStub android:id="@+id/stub_import" 
android:inflatedId="@+id/panel_import" 
android:layout="@layout/progress_overlay" 
android:layout_width="fill_parent"
 android:layout_height="wrap_content" 
android:layout_gravity="bottom" />

载入 ViewStub当您要载入用 ViewStub 申明的 Layout 时,要么用 setVisibility(View.VISIBLE) 设置它的可知性,要么调用其 inflate() 方法。
上边以在八个搭架子main.xml中投入网络错误时的提醒页面network_error.xml为例。main.mxl代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" 
android:layout_height="match_parent"
 >  …… 
<ViewStub android:id="@+id/network_error_layout" android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:layout="@layout/network_error" 
/> </RelativeLayout>

其中network_error.xml为唯有在互联网错误时才需求出示的布局
setVisibility(View.VISIBLE)方式

View viewStub = 
((ViewStub)findViewById(R.id.stub_import));
viewStub.setVisibility(View.VISIBLE);
netErrorLayout = findViewById(R.id.net_error_layout))

inflate方式

View netErrorLayout = ((ViewStub) 
findViewById(R.id.net_error_layout)).inflate();

瞩目:inflate() 方法会在渲染实现后回来给被 inflate 的视图,所以您无需再调用 findViewById() 去搜索这几个因素。减弱inflate的次数,也会对功能有好几进级。而setVisible格局还需求再一次findViewById找到ViewStub中的成分。
假定 ViewStub 可知或是被 inflate 了,ViewStub 成分就不设有了。取代他的是被 inflate 的 Layout,其 id 是 ViewStub 上的 android:inflatedId 属性。(ViewStub 的 android:id 属性仅在 ViewStub 可见在此以前可用)
瞩目:ViewStub 的三个顽固的病魔是,它方今不补助使用 标签的 Layout

四 ListView的优化
倘使你有二个包括复杂恐怕每一种项 (item) 包罗很许多据的 ListView ,那么上下滚动的属性恐怕会骤降。本节给您有的有关如何把滚动变得更通畅的唤醒。保持程序流畅的重视,是让主线程(UI 线程)不要进行大批量运算。你要确认保障在其余线程实施磁盘读写、互连网读写或是 SQL 操作等。为了测量检验你的运用的情事,你能够启用 StrictMode。
4.1 使用后台线程
您应该把主线程中的耗费时间间的操作,提取到贰个后台线程中,使得主线程只关心UI 美术。
4.2 在 View Holder 中填入视图对象
运用convertView、你的代码恐怕在 ListView 滑动时平常应用 findViewById(),这样会骤降品质。即便是 Adapter 重返叁个用于回收的 convertView,你还是须要寻找那么些因素并更新它。避免频仍调用 findViewById() 的法子之一,正是选拔 View Holder(视图占位符)设计形式。
ViewHolder 存款和储蓄了标签下的种种视图。那样您不要反复查找这一个成分:

static class ViewHolder { 

TextView text; TextView timestamp; ImageView icon; 
ProgressBar progress; int position;
}

接下来,在 Layout 的类中生成二个 ViewHolder 对象:

javaViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
...convertView.setTag(holder);

那般您就足以轻易收获每一种视图,并非用 findViewById() 来不断探索视图,节省了可贵的运算时间。
4.3 getView不要做复杂的操作
因为每一条Item移入荧屏的时候,都会调用getView,不要在getView中做复杂的操作,不要频仍的创造对象。Item点击的拍卖不要超前做。极度是在快捷滑动的时候,会招致频仍的调用getView。
五 优化提醒
尽恐怕接纳RelativeLayout,可以降低层级的嵌套。慎用LinearLayout的layout_weight属性,能够利用RelativeLayout的centerHorizontal=”true”、toLeft、toRight替代
六 书写标准上的优化
6.1 Id的命名
为了便利分辨,你能够依附自个儿的专门的职业来对脚下分界面包车型大巴财富开展命名,举个例子当前是登陆分界面,那么您能够如此命名:login_edit_usernamelogin_edit_passwordlogin_btn_submitlogin_txv_forgot_pass
6.2 财富的命名
ic_action_add, ic_action_location (ActionBar Icons)ic_play, ic_save (General Icons)ic_tab_music, ic_tab_more (Tab Icons)
6.3 通用的能源命名
对style.xml和dimens.xml的命名能够通用的尽心通用,因为二个项指标核心视图非常多都以通用的,比如ActionBar、ListView等,标准通用的命名可以很有益于的移植到任何体系中。

<color name="list_item_large">#FCA558</color> 
<color name="list_item_small">#FBA228</color> 
<dimen name="list_item_large">24dp</dimen>
 <dimen name="list_item_small">18dp</dimen>
 <!-- 简单ListView样式 --><style name="list_view_style_default"> <item name="android:layout_width">fill_parent</item>
 <item name="android:layout_height">wrap_content</item>
  ...</style>

转载自:

http://www.lightskystreet.com/2015/01/19/android-layout-optimize/

参谋文献
best-practices-for-android-user-interface
layout-performance

本文由华夏彩票发布于编程应用,转载请注明出处:Android布局优化,分界面多情状加载

您可能还会对下面的文章感兴趣: