Android使用DataBinding和Merge引发的血案

Android使用DataBinding和Merge引发的血案

1.前言:

相信Databinding和Merge大家都不陌生,今天讲解的是Databinding和Merge一起使用遇到的问题,在父布局使用,引用的布局使用Merge会导致id找不到,运行时直接崩溃了,废话不多说,直接上代码。

2.引入ViewBinding:

kotlin 复制代码
viewBinding {
    enable =  true
}

3.主界面布局:

kotlin 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:text="这是DataBinding使用示例"
        android:gravity="center"
        android:textSize="20sp"
        android:textColor="@color/white"
        android:background="@color/design_default_color_primary_dark"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <include
        android:id="@+id/test_layout"
        layout="@layout/layout_test"/>
</androidx.constraintlayout.widget.ConstraintLayout>

4.引用布局:

kotlin 复制代码
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/iv_local"
        android:layout_width="100dp"
        android:layout_height="120dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="40dp"
        android:gravity="center"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_background"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center|start"
        android:textSize="16sp"
        android:text="标题"
        android:textColor="@color/design_default_color_primary_dark"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="40dp"
        app:layout_constraintLeft_toRightOf="@id/iv_local"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"  />

    <TextView
        android:id="@+id/author"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center|start"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:textSize="16sp"
        android:text="张2"
        android:maxLines="1"
        android:ellipsize="end"
        android:textColor="@color/design_default_color_primary_dark"
        app:layout_constraintLeft_toRightOf="@id/iv_local"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title" />

    <TextView
        android:id="@+id/content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:gravity="center|start"
        android:text="先说优点吧,Paging 的使用,需要配合ViewModel,LiveData等控件,数据的请求感知并绑定页面的生命周期,避免了内存泄漏。还需要绑定DataSource和DataSource的Factory,能无痕加载更多数据,一定程度上提高用户体验。"
        android:textColor="@color/design_default_color_primary_dark"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:maxLines="3"
        android:ellipsize="end"
        app:layout_constraintLeft_toRightOf="@id/iv_local"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/author" />

</merge>

5.测试代码如下:

kotlin 复制代码
package com.cloud.databindingmergedemo

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.LayoutInflaterCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.cloud.databindingmergedemo.databinding.ActivityMainBinding
import com.cloud.databindingmergedemo.databinding.LayoutTestBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding:ActivityMainBinding
    private lateinit var testView:TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)

        setContentView(binding.root)
        initView()
    }

    private fun initView() {
        testView = binding.testLayout.title
    }
}

6.运行后的报错信息如下:

从日志可以看出,报错信息很明显,在testView = binding.testLayout.title这里找不到testLayout的id,

7.解决方法如下:

直接使用引用布局的名称绑定在父布局中,然后找到引用布局去获取里面控件的id

kotlin 复制代码
class MainActivity : AppCompatActivity() {
    private lateinit var binding:ActivityMainBinding
    private lateinit var testView:TextView
    private lateinit var testBinding: LayoutTestBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        testBinding = LayoutTestBinding.bind(binding.main)
        setContentView(binding.root)
        initView()
    }

    private fun initView() {
        testView = testBinding.title
    }
}

8.运行的效果如下:

这时发现一个问题,布局重叠了,那我把依赖在父布局修改一下试试

9.修改后的代码如下:

kotlin 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:text="这是DataBinding使用示例"
        android:gravity="center"
        android:textSize="20sp"
        android:textColor="@color/white"
        android:background="@color/design_default_color_primary_dark"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <include
        app:layout_constraintTop_toBottomOf="@id/textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        layout="@layout/layout_test"/>
</androidx.constraintlayout.widget.ConstraintLayout>

10.在引用布局设置依赖:

这时发现竟然生效了,效果如下:

发现有点拥挤,于是加上20dp间距,android:layout_marginTop="20dp"

kotlin 复制代码
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">

    <ImageView
        android:id="@+id/iv_local"
        android:layout_width="100dp"
        android:layout_height="120dp"
        android:layout_marginStart="20dp"
        android:gravity="center"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_background"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textview"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center|start"
        android:textSize="16sp"
        android:text="标题"
        android:textColor="@color/design_default_color_primary_dark"
        android:layout_marginLeft="20dp"
        app:layout_constraintLeft_toRightOf="@id/iv_local"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textview" />

    <TextView
        android:id="@+id/author"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center|start"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:textSize="16sp"
        android:text="张2"
        android:maxLines="1"
        android:ellipsize="end"
        android:textColor="@color/design_default_color_primary_dark"
        app:layout_constraintLeft_toRightOf="@id/iv_local"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title" />

    <TextView
        android:id="@+id/content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:gravity="center|start"
        android:text="先说优点吧,Paging 的使用,需要配合ViewModel,LiveData等控件,数据的请求感知并绑定页面的生命周期,避免了内存泄漏。还需要绑定DataSource和DataSource的Factory,能无痕加载更多数据,一定程度上提高用户体验。"
        android:textColor="@color/design_default_color_primary_dark"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="20dp"
        android:maxLines="3"
        android:ellipsize="end"
        app:layout_constraintLeft_toRightOf="@id/iv_local"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/author" />

</merge>

11.最后的效果如下:

12.一个小tips:

  • tools:parentTag
    该属性主要来指定父级view-tag;在自定义组合布局时,配合 标签,可以消除多余的层级。
  • 如,定义了一个布局,它的根 布局标签是 LinearLayout;要把该布局整体用一个自定义view来关联操作。
    view中,通常有一句:LayoutInflater.from(context).inflate(R.layout.xxx, this, true)
    注意最后一个参数,属性为true:即 将inflate出的布局,attachToRoot 到 this。
    这就会多一个层级,当前this 是 LinearLayout, 布局本身也是 LinearLayout ...
    所以要将 xml 的根标签 LinearLayout 改成:
  • <merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:parentTag="LinearLayout"
    ... >
  • 我这里使用的是约束布局所以是tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"

13.总结:

以上技术今天的内容,在使用Merge优化布局时,结合Databinding或ViewBinding如果使用不当会出现问题,导致app崩溃,好了,这里提前祝大家元旦快乐,新的一年万事如意,工作顺利.

  • 使用tools:parentTag多余层级
  • 使用引用布局的名称LayoutTestBinding绑定id
  • 设置好布局的位置和约束

14.demo地址如下:

https://gitee.com/jackning_admin/animation-test-demo

相关推荐
阿巴斯甜17 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker17 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952718 小时前
Andorid Google 登录接入文档
android
黄林晴19 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android