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

相关推荐
maki07715 小时前
虚幻版Pico大空间VR入门教程 05 —— 原点坐标和项目优化技巧整理
android·游戏引擎·vr·虚幻·pico·htc vive·大空间
千里马学框架16 小时前
音频焦点学习之AudioFocusRequest.Builder类剖析
android·面试·智能手机·车载系统·音视频·安卓framework开发·audio
fundroid19 小时前
掌握 Compose 性能优化三步法
android·android jetpack
TeleostNaCl20 小时前
如何在 IDEA 中使用 Proguard 自动混淆 Gradle 编译的Java 项目
android·java·经验分享·kotlin·gradle·intellij-idea
旷野说21 小时前
Android Studio Narwhal 3 特性
android·ide·android studio
maki0771 天前
VR大空间资料 01 —— 常用VR框架对比
android·ue5·游戏引擎·vr·虚幻·pico
xhBruce1 天前
InputReader与InputDispatcher关系 - android-15.0.0_r23
android·ims
领创工作室1 天前
安卓设备分区作用详解-测试机红米K40
android·java·linux
hello_ludy1 天前
Android 中的 mk 和 bp 文件编译说明
android·编译
maki0771 天前
VR大空间资料 03 —— VRGK使用体验和源码分析
android·vr·虚幻·源码分析·oculus·htc vive·vrgk