12.13 XML布局 和 LiveData

1.xml布局

Java代码调用方法控制UI 缺点:繁琐不易解耦;xml布局便捷但有失灵活

xml文件编译时,都需要通过main函数中onCreate来调用,用法如下

项目里 override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)

   ……

}

博客里

@Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_linear_layout);  //‘R’系统给声明的静态变量 所有子类通过’R’调用,其路径app -> src -> main -> res,整句指res-> layout文件夹下自己定义的.xml

    }

疑问:2种写法的区别?优缺点?

1.1线性布局LinearLayout

1.1.1常见问题

1)文字没对齐;原因:LinearLayout默认子控件按照基准线对齐;解决:在 LinearLayout中添加属性android:baselineAligned=“false” 使得子控件不按照基线对齐

1.1.2.orientation布局中组件排列方式,horizontal水平(只有水平的设置才起作用即top bottom center_vertical)和vertical(只垂直设置才起作用即left right center_horizontal)

1.1.3.gravity控件组件包含的子元素对齐方式,如left bottom

1.1.4.layout_gravity组件在父容器的对齐方式

1.1.5.layout_width 和layout_height通常wrap_content(组件实际大小)match_parent填满父容器 fill_parent

1.1.6.layout_margin外边距 layout_padding内边距

1.1.7.id设置资源id 在Java代码中可findViewById(id) 找到组件 如@+id/addGoodsActivity

1.1.8.bacground背景图或6位16进制表示颜色

1.1.9.layout_weight等比例划分区域 (通常权重方向宽度layout_width 设置0dp,若未设置,控件占指定宽度加根据权重来分配的空间)

根据控件该值和布局中所有控件的该值的和的比值为该控件分配占用的区域;如4个TextView的layout_weight都为1,将拉伸到总大小的1/4

0按原大小显示,不会被拉伸;大于0,会减去layout_weight = 0的控件宽度或高度,再用剩余的按比例分配

1.1.10.divider分割线 设置分割线图片,showDividers设置分割线位置,4个可选值none,middle,beginning,end, dividerPadding设置padding

1.1.11.LinearLayout的weightSum属性:布局中只有1个控件,让它占1/2宽度,设置该值为2

1.2 相对Relative Layout

1.2.1.gravity容器内组件的对齐方式

ignoreGravity为true不受gravity属性影响

1.2.2根据父容器定位

layout_alignParentLeft/Right/Top/Bottom左/右/顶/底对齐  android:layout_centerHorizontal/Vertical/InParent水平/垂直居中/中间  android:layout_alignWithParentIfMissing 如果对应的兄弟元素找不到的话就以父元素做参照物

1.2.3根据兄弟组件定位

layout_toLeftOf/toRightOf/above/below参考组件的左边/右边/上/下 layout_alignLeft/Right/Top/Bottom对齐参考组件的上/下/左/右边界

1.2.4margin外边距/偏移

layout_margin组件上下左右的偏移量  layout_marginLeft/Right/Top/Bottom组件距离上/下/左/右的偏移量

1.2.5padding填充/内边距

android:padding元素内部上下左右填充一定边距  paddingLeft/Right/Top/Bottom组件距离上/下/左/右内边距

1.3条件布局 Constraint Layout

1.3.1. 优点:

性能更优,较线性、条件布局少嵌套;适配性更好,大小距离都能用比例设置;书写简单;可视化编辑

1.3.2. app: layout_constraintLeft_toLeftOf/Left_toRightOf/Right_toLeftOf/Right_toRightOf/Top_toTopOf/Top_toBottomOf/Bottom_toTopOf/Bottom_toBottomOf/Start_toEndOf/Start_toStartOf/End_toStartOf/End_toEndOf/Baseline_toBaselineOf

layout_constraint*属性的值可以是某id或parent父布局

1.3.3. margin有2种 1)app: layout_goneMarginEnd只有id为@+id/right_top被gone的时候生效;一种就是android:layout_marginEnd,任何时候都生效

1.3.4. view gone 当b设为gone之后,他的宽、高、margin都失效了,变为一个点了,但它的constrain还生效,位于指定的位置。c还是可以继续以他为锚点

注意1)尽量使用invisible 2)尽量其他view的布局不依赖会gone的view 3)当constrainleft的锚点gone时,layout_goneMarginLeft将生效 缺点:只能设置固定距离,灵活性不高

1.3.5. 居中及bias

设置app:layout_constraintLeft_toLeftOf=“parent”,则view会贴着父view的左边,设置app:layout_constraintRight_toRightOf=“parent” 则会贴着右边,那如果两个都设置会居中

layout_constraintHorizontal_bias必须给控件左右都加约束才生效 layout_constraintVertical_bias必须给控件上下都加约束才生效  bias即偏移量,他们的取值范围从0~1,0即挨着左边,1是挨着右边

1.3.6. view尺寸

1.3.6.1. wrap_content、指定尺寸如@dimen/dp_180(res->values->dimens xml里定义的dp_180)、match_parent(虽然官方不推荐使用match_parent)外,还可以设置为0dp(官方取名叫MATCH_CONSTRAINT),0dp在constraint可不是指大小是0dp,而是有特殊含义的,会随设置不同含义不同

1.3.6.2. layout_constraintWidth_default,有三个取值,作用如下:spread,默认值,占用所有的符合约束的空间;percent按照父布局的百分比设置;wrap,匹配内容大小但不超过约束限制(和直接指定宽度为wrap_content的区别就是不超过约束限制)

1.3.6.3. ratio

layout_constraintDimensionRatio,即宽和高成一定的比例,其值可以是"width:height"的形式,也可以是width/height的值 生效的前提:宽和高中有一项为0dp,有constraint

一项0dp,则该值按比例计算出来 如高为20dp,宽为0dp,radio为"2:1",宽为40dp;两项都为0dp,尺寸为满足约束的最大值并保持比例 可通过在前面加H、W来指定是哪一个边需要计算。例如"H,2:1",则是指宽度匹配约束,高度是宽度的1/2

1.3.6.4. max min

设置min的宽度和高度,必须是要控件的layout_width或者layout_height为wrap_content或者0dp时。

给控件设置max的宽度或者高度的时候,必须是要控件的layout_width或者layout_height为0dp,只是设置了0dp,如果没给控件添加对应的左右约束或者上下约束,比如没有设置左右约束,那么layout_constraintWidth_max设置的再大也不会超过整个控件的wrap_content的长度

1.3.7.1.  GuideLine虚拟参考线,方便其他view以它为锚点布局,有水平参考线和竖直参考线两种。当布局没合适参考view,而建一个专门用于定位的View又会太重,这种情况正是GuideLine的用武之地

Guideline的大部分的属性如layout_width都是不会生效的,而它的位置的确定是由下面三个属性之一来确定的:

layout_constraintGuide_begin/end:距离父布局的左边或者上边/右边或下边距离  layout_constraintGuide_percent:百分比,0~1,距离父布局的左边或者上边占父布局的比例

1.3.7.2.  Barrier 屏障,一个虚拟View  <android.support.constraint.Barrier

Button只能设置一个View作为锚点,设置了上面就顾不了下面了 而Barrier,可以设置N个View作为锚点

1.3.7.3. Guideline和Barrier的区别

共同点:都是辅助约束

区别:当控件比如出现切换手机语言,而造成控件上的文本显示长度出现变化的时候,Guideline并不会随着控件的长度变化而变化会造成约束不灵活;如果控件的内容是不变的,可以使用Guideline

而Barrier可以根据控件的宽高变化,灵活移动位置。控件宽高是随着内容动态变化的,建议使用Barrier

2.LiveData

2.1概念

可观察的数据存储器类  与常规的可观察类不同,LiveData 具有生命周期感知能力,仅更新处于活跃( STARTED 或 RESUMED )生命周期状态的应用组件(如 Activity、Fragment 或 Service)观察者,为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知

2.2优势

确保界面符合数据状态     遵循观察者模式,底层数据变化,Livedata会通知Observer对象

不会发生内存泄漏            观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理

不会因 Activity 停止而导致崩溃         观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件

不再需要手动处理生命周期   LiveData可感知组件生命周期,界面组件只是观察相关数据,不会停止或恢复观察

数据始终保持最新状态  生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据

适当的配置更改    由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据

共享资源       能用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象

2.3使用

1)viewModel中 创建LiveData实例以存储某类型数据 2)在界面控制器(如 Activity 或 Fragment)中 创建可定义onChanged()方法(控制当 LiveData 对象存储的数据更改时会发生什么)的Observer

3)在界面控制器(如 Activity 或 Fragment)中  用 observe() 方法(采用 LifecycleOwner 对象使Observer对象订阅LiveData)将 Observer 对象附加到 LiveData 对象

2.3.1. 创建

可用于任何数据的封装容器,包括可实现Collections的对象,如List; 在viewModel中,可通过getter方法访问

2.3.2.  观察

多数情况, onCreate() 方法是开始观察 LiveData 对象的正确着手点原因如下:

  • 确保系统不会从 Activity 或 Fragment 的 onResume() 方法进行冗余调用。
  • 确保 Activity 或 Fragment 变为活跃状态后具有可以立即显示的数据。一旦应用组件处于 STARTED 状态,就会从它正在观察的 LiveData 对象接收最新值

2.3.3.  更新

没有公开可用的方法来更新存储的数据

MutableLiveData 类将公开 setValue(T) 和 postValue(T) 方法,如果您需要修改存储在 LiveData 对象中的值,则必须使用这些方法。 在 ViewModel 中用 MutableLiveData,只会向观察者公开不可变的LiveData

2.3.4.LiveData与Room一起用

Room持久性库支持返回LiveData对象的可观察查看(数据库访问对象DAO的一部分)数据库更新,Room自动更新LiveData 对象所需的所有代码。

在需要时,生成的代码会在后台线程上异步运行查询。此模式有助于 使界面中显示的数据 与 存储在数据库中的数据 保持同步

2.3.5.LiveData与协程一起用

2.4应用架构中的LiveData

activity 和 fragment 不应保留 LiveData 实例,只是显示数据,不保持状态。持续不保留数据,可以使编写单元测试变得更轻松。

LiveData 并不适合用于处理异步数据流,但可以使用 LiveData 转换和 MediatorLiveData实现此目的。缺点:用于组合数据流的功能非常有限,并且所有 LiveData 对象(包括通过转换创建的对象)都会在主线程中观察到

在应用其他层用数据流,用 asLiveData() 在 ViewModel 中将 Kotlin Flow 转换成 LiveData

2.5. 扩展LiveData

有活跃观察者时,会调用 onActive() 方法,从此方法开始观察更新;没任何活跃观察者时,调用 onInactive() 方法,没观察者就没有理由与 StockManager 服务保持连接。setValue(T) 方法将更新 LiveData 实例的值,并将更改告知活跃观察者

observe() 方法将与 Fragment 视图关联的 LifecycleOwner 作为第一个参数传递。这样做表示此观察者已绑定到与所有者关联的 Lifecycle 对象,这意味着:

  • 如果 Lifecycle 对象未处于活跃状态,那么即使值发生更改,也不会调用观察者。
  • 销毁 Lifecycle 对象后,会自动移除观察者

2.6转换LiveData

在将 LiveData 对象分派给观察者之前对存储在其中的值进行更改,或者您可能需要根据另一个实例的值返回不同的 LiveData 实例。Lifecycle 软件包会提供 Transformations 类,该类包括可应对这些情况的辅助程序方法。

Transformations.map()

对存储在 LiveData 对象中的值应用函数,并将结果传播到下游。

疑问1. Demo在哪设置颜色? 2.app action xml file 和Layout xml 和values xml区别  3. 阻塞主线程?4.安卓里单例的写法?

companion object {

        private lateinit var sInstance: StockLiveData

        @MainThread

        fun get(symbol: String): StockLiveData {

            sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)

            return sInstance

        }

    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值