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

相关推荐
雨白4 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹6 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空7 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭8 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日9 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安9 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑9 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟13 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡14 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0014 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体