美文网首页Android BUG
Android ViewBinding 处理

Android ViewBinding 处理

作者: 超级呆 | 来源:发表于2023-01-28 16:04 被阅读0次

概述 (Summary)

最近在项目中,遇到一个关于使用ViewBinding的问题

在使用<include />标签且layout的文件来自aar中的文件时,
生成的ViewBinding中映射layout的类型是View,而不是我们期望的XxxBinding
但是如果layout文件来自同一个工程中的另一个module,则会生成XxxBinding类型。

问题 (Issue)

layout文件:

<!-- activity_awesome.xml -->
<androidx.constraintlayout.widget.ConstraintLayout>
    <include android:id="@+id/includes" layout="@layout/included_buttons" />
</androidx.constraintlayout.widget.ConstraintLayout>
  
<!-- included_buttons.xml 在aar中-->
<androidx.constraintlayout.widget.ConstraintLayout>
    <Button android:id="@+id/include_me" />
</androidx.constraintlayout.widget.ConstraintLayout>

生成的Binding文件

public final class ActivityAwesomeBinding implements ViewBinding {

  @NonNull
  public final View includes;
}

分析 (Analysis)

  • 对比正常生成和非正常生成时, gradle tasks的执行情况

    当layout文件在同工程的另一个module中,能够正常生成XxxBinding类型时,会多执行该module的相关tasks:
    dataBindingMergeDependencyArtifactsDebug
    dataBindingMergeGenClassesDebug
    dataBindingGenBaseClassesDebug

  • 分析Android Gradle Plugin源码

    android.databinding.tool.writer.ViewBinderKt#toViewBinder 该方法直接忽略了aar中layout对应的XxxBinding

        // Check to make sure that the ID matches a binding. Ignored tags like <merge> or <fragment>
        // might have an ID but not have an actual binding. Only use ID if a match was found.
        val rootBinding = bindings.singleOrNull { it.id == id }
        if (rootBinding != null) {
            return RootNode.Binding(rootBinding)
        }

结论 (Conclude)

目前AGP 7.2.0 处理ViewBinding生成代码的方式,虽然aar的模块在生成aar的阶段,已经生成了XxxBinding.java文件,但是由于没有运行ViewBinding相关的Gradle Task,导致依赖aar的模块没有将aar中的XxxBinding.java加入到后续配置查询的binding list中,最终该类型被忽略,默认返回了View类型

替代方法 (Workaround)

由于底层插件的限制,我们没有办法直接使用XxxBinding (或者说时间成本高,没有必要自己手动写一个生成代码的插件),但是我们依然可以映射出XxxBinding

// Activity.kt
class Activity {
    private val includedButtonsBinding :IncludedButtonsBinding 
    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val rootBinding = ActivityAwesomeBinding.inflate(inflater, container, false)
        includedButtonsBinding = IncludedButtonsBinding.bind(ActivityAwesomeBinding.includes)
        return rootBinding.root
    }
}

其他 (others)

Google官方文档推荐ViewBinding学习博客

相关文章

网友评论

    本文标题:Android ViewBinding 处理

    本文链接:https://www.haomeiwen.com/subject/ntayhdtx.html