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

相关推荐
weixin_460783875 小时前
Flutter解决TabBar顶部页面切换导致页面重载问题
android·javascript·flutter
qhs15736 小时前
Kotlin字符串操作在Android开发中的应用示例
android·开发语言·kotlin
网络安全(king)8 小时前
Android networkSecurityConfig 代码配置
android
LuXi_foryou9 小时前
【2025深夜随笔】简单认识一下Android Studio
android·ide·android studio
缘来的精彩9 小时前
Android Studio Gradle 8.0 适配指南
android·ide·android studio
星仔_X9 小时前
Android Studio安装配置
android·ide·android studio
驜鸈9 小时前
MySQL 的EXPLAIN 计划 type 字段详细说明
android·数据库·mysql
二流小码农9 小时前
鸿蒙开发:wrapBuilder传递参数
android·ios·harmonyos
ljx140005255010 小时前
推荐一个基于Koin, Ktor & Paging等组件的KMM Compose Multiplatform项目
android·kotlin
lrydnh11 小时前
数据库语句
android·数据库