Skip to content

Latest commit

 

History

History
414 lines (277 loc) · 16.7 KB

README_CN.md

File metadata and controls

414 lines (277 loc) · 16.7 KB

Binding

Simple API implement DataBinding and ViewBinding. Welcome star
简单的 API 实现 DataBinding 和 ViewBinding,欢迎 star

English  ·  中文

如果图片无法查看,请点击这里查看 图例1 | 图例2

关于 Binding

因 Jcenter 即将被废弃,已经将 Binding 迁移到 mavenCentral

Binding 简化 DataBinding 和 ViewBinding 的使用, 只需要一行代码即可实现 DataBinding 和 ViewBinding。

Binding 未来的规划提供通用的 findViewById 解决方案,,因技术的迭代更新从 butterknife 、 DataBinding 、 Kotlin 合成方法(Synthetic 视图)到现在 ViewBinding , 未来也有可能出现新的技术,无论技术怎么变化,只需要更新 Binding ,对外的使用保持不变。

感谢小伙伴们的建议,目前 Binding 已经适配了大量的场景,同时也提供了很多 DataBinding 和 ViewBinding 实战案例,如果你在使用过程中遇到 Binding 不兼容的场景,欢迎提 issue,我会尽快解决。

如果这个仓库对你有帮助,请在仓库右上角帮我 star 一下,非常感谢你的支持,同时也欢迎你提交 PR ❤️❤️❤️

Binding 具有以下优点:

  • 支持在自定义 ViewGroup 使用 DataBinding 或者 ViewBinding
  • 提供了很多实战案例包含 AtivityFragmentDialogAdapterincludemergeViewStubNavigation 、 数据双向绑定 等等场景
  • 简单的 API 只需要一行代码即可实现 DataBinding 或者 ViewBinding
  • 支持在 ActivityAppCompatActivityFragmentActivityFragmentDialog 中的使用 DataBinding 或者 ViewBinding
  • 支持在 ListAdapterPagedListAdapterPagingDataAdapterRecyclerView.Adapter 中的使用 DataBinding 或者 ViewBinding
  • 支持在 Navigaion Fragment 管理框架、 BottomSheetDialogFragment 等等场景中使用 DataBinding 和 ViewBinding
  • 避免大量的模板代码
  • 避免内存泄露,具有生命周期感知能力,当生命周期处于 onDestroyed() 时会自动销毁数据

Download

将下列代码添加在 Project 级别的 build.gradle 文件中

allprojects {
    repositories {
        // aliyun center 包含 mavenCentral 和  jcenter
        maven { url "https://maven.aliyun.com/repository/public" }
        // maven
        mavenCentral()
    }
}

添加依赖

将下列代码添加在模块级 build.gradle 文件中,并且需要开启 DataBinding 或者 ViewBinding

android {
    buildFeatures {
        dataBinding = true
        viewBinding = true
    }
}

dependencies {
    implementation 'com.hi-dhl:binding:${binding_version}'
}

binding 最新版本

简单的 API

Binding 统一封装了 DataBinding 和 ViewBinding, 提供了简单的 API 如下所示。

ViewBinding 中的使用

val binding: ActivityViewBindBinding by viewbind()

DataBinding 中的使用

val binding: ActivityDataBindBinding by databind(R.layout.activity_data_bind)
或者
val binding: ActivityDataBindBinding by databind()

我们来看一下在 AtivityFragmentDialogAdapterincludemergeViewStubNavigationViewGroup 、 数据双向绑定 等等场景中如何使用。

使用

在自定义 ViewGroup 中使用 DataBinding 和 ViewBinding,

  • ViewBinding 两种用法

    • 当根布局是非 merge 标签,使用此方法进行初始化 val binding: LayoutViewCustomBinding by viewbind()
    • 当根布局为 merge 标签,使用此方法进行初始化 val binding: LayoutViewCustomBinding by viewbind(this)
  • DataBinding 的使用

    val binding: LayoutViewCustomDataBinding by databind(R.layout.layout_view_custom_data)
    

详细的 Demo 示例如下所示。

class ViewBindCustomView @JvmOverloads constructor(
    context: Context,
    attr: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : LinearLayout(context, attr, defStyleAttr) {

    // ViewBinding
    
    // 当根布局为 merge 标签,使用此方法进行初始化
    val binding: LayoutViewCustomBinding by viewbind(this)
    
    // 当根布局是非 merge 标签,使用此方法进行初始化
    val binding: LayoutViewCustomBinding by viewbind()

    // DataBinding
    val binding: LayoutViewCustomDataBinding by databind(R.layout.layout_view_custom_data)

    init {
        with(binding) {
            result.setText("在自定义 ViewGroup 中使用 DataBinding 或者 ViewBinding")
        }
    }
}

在 Adapter 中使用 DataBinding 和 ViewBinding,只需要在 ViewHolder 中添加 by viewbind() 或者 by databind() 即可,示例如下所示,查看详细示例

class ProductViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    
    // 通过 DataBinding 绑定的 itemView
    val binding: RecycleItemProductBinding by databind()

    fun bindData(data: Product?, position: Int) {
        binding.apply {
            product = data
            executePendingBindings()
        }
    }
}

class ProductViewHolderHeader(view: View) : RecyclerView.ViewHolder(view) {

    // ViewBinding
    val binding: RecycleItemProductHeaderBinding by viewbind()

    fun bindData(data: Product?, position: Int) {
        binding.apply {
            name.text = "通过 ViewBinding 绑定的 head"
        }
    }
}

ActivityAppCompatActivityFragmentActivity 中使用,添加 by viewbind() 或者 by databind(R.layout.activity_main) 即可,示例如下所示。

class MainActivity : AppCompatActivity() {

    // DataBinding
    val binding: ActivityMainBinding by databind(R.layout.activity_main)
    
    // ViewBinding
    val binding: ActivityMainBinding by viewbind()
}

Fragment 中提供了两种方式:

方式一:不建议使用,建议直接使用方式二,详见 issue #13

class FragmentNav1 : Fragment() {
    
    // DataBinding
  	val binding: FragmentMainBinding by databind()
    
    // ViewBinding
  	 val binding: FragmentMainBinding by viewbind()
  
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return binding.root
    }
}

方式二:

class FragmentNav1 : Fragment(R.layout.fragment_main) {
    
    // DataBinding
  	val binding: FragmentMainBinding by databind()
    
    // ViewBinding
  	 val binding: FragmentMainBinding by viewbind()
  
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.apply { textView.setText("Binding") }
    }
}

Dialog 中使用方式如下所示。

class AppDialog(context: Context) : Dialog(context, R.style.AppDialog) {

    // DataBinding
    val binding: DialogAppBinding by databind(R.layout.dialog_data_binding)
    
    // ViewBinding
    val binding: DialogAppBinding by viewbind()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.apply { result.setText("DialogAppBinding") }
    }
}

或者添加具有生命周期感知的 Dialog

class AppDialog(context: Context,lifecycle: Lifecycle) : Dialog(context, R.style.AppDialog) {

    // DataBinding 监听生命周期
    val binding: DialogAppBinding by databind(R.layout.dialog_data_binding, lifecycle)
    
    // ViewBinding 监听生命周期
    val binding: DialogAppBinding by viewbind(lifecycle)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.apply { result.setText("DialogAppBinding") }
    }
}

扩展方法,支持 DataBinding 初始化的时候绑定数据,感谢 @br3ant 贡献,查看详细示例

val binding: ActivityDataBindBinding by databind(R.layout.activity_data_bind) {
    val account = Account()
    account.name = "test"
    this.account = account
}

不想为某个布局生成 binding 类,将下面属性添加到布局文件的根视图中

<LinearLayout tools:viewBindingIgnore="true" >
</LinearLayout>

混淆

-keepclassmembers class ** implements androidx.viewbinding.ViewBinding {
    public static ** bind(***);
    public static ** inflate(***);
}

更新记录

2023-04-13(V1.2.0)

  • 兼容 lifecycle 2.6.0 FullLifecycleObserver 被删除的问题

2022-10-07(V1.1.9)

  • 兼容 jdk >= 1.8

2022-7-13(V1.1.7)

  • 兼容不传 ViewGroup 的情况#34

2022-5-12(V1.1.5)

  • 修改 ViewGroup 销毁的时候释放资源 #33

2022-5-03(V1.1.4)

  • 修复了生命周期问题
  • 修复了销毁之后再次使用,由于 delegate property 会被再次初始化,出现的异常 #31

2021-5-09(V1.1.3)

  • 修复在 ViewGroup 中是用 merge 标签,inflate 无法找到的问题 #26

2021-3-09(V1.1.2)

  • 修改 FragmentDataBinding 绑定 View 生命周期为 viewLifecycleOwner #18
  • 迁移到 mavenCentral

2021-1-25(V1.0.9)

  • 修复了 Fragment lifecycle 和 Fragment 中的 View 生命周期不一致问题 #15
  • 修复了 Fragment 根部局的 layout 属性失效的问题 #13

2021-1-14(V1.0.8)

  • 支持在自定义 ViewGroup 使用 DataBinding 或者 ViewBinding
  • 增加了在 ViewGroup 中的使用案例

2020-12-31

2020-12-28(V1.0.6)

  • 支持 Activity 和 Fragment 自动绑定 LifecycleOwner。详见 issue

2020-12-21(V1.0.5)

  • 支持在 navigation fragment 中使用 DataBinding 和 ViewBinding,查看详细示例

2020-12-17(V1.0.4)

  • 支持所有与 RecyclerView.ViewHolder 相关的 Adapter(ListAdapter、PagingDataAdapter、RecyclerView.Adapter 等等)使用 DataBinding 和 ViewBinding,查看详细示例

  • 支持通过 by databind 初始化,同时可以绑定数据,感谢 @br3ant 贡献,查看详细示例

2020-12-15(V1.0.3)

  • 添加了 DataBinding 在 Dialog 中的使用, by databind(R.layout.dialog_data_binding) 或者 by databind(R.layout.dialog_data_binding, lifecycle)
  • 处理了 大于等于 Android 10.0小于 Android 10.0 生命周期问题,当处于 onDestroyed() 时会自动销毁数据
  • 最低 SDK 版本降低至 14

2020-12-14:

  • Demo 增加 DataBinding 示例
  • Demo 增加 ViewBinding 示例
  • Demo 增加 kotlin-parcelize 示例

2020-12-13(V1.0.1)

  • 添加了 ViewBinding 在 Dialog 中的使用, by viewbind() 或者 by viewbind(lifecycle)

2020-12-12(V1.0.0)

  • 添加 DataBinding 和 ViewBinding 在 ActivityAppCompatActivityFragmentActivityFragment 中的使用
  • 避免模板代码,只需要一行代码即可实现 DataBinding 或者 ViewBinding
  • 当生命周期处于 onDestroyed() 时会自动销毁数据

联系我

  • 个人微信:hi-dhl
  • 公众号:ByteCode,包含 Jetpack ,Kotlin ,Android 10 系列源码,译文,LeetCode / 剑指 Offer / 多线程 / 国内外大厂算法题 等等一系列文章


最后推荐我一直在更新维护的项目和网站:

  • 计划建立一个最全、最新的 AndroidX Jetpack 相关组件的实战项目 以及 相关组件原理分析文章,正在逐渐增加 Jetpack 新成员,仓库持续更新,欢迎前去查看:AndroidX-Jetpack-Practice

  • LeetCode / 剑指 offer / 国内外大厂面试题 / 多线程 题解,语言 Java 和 kotlin,包含多种解法、解题思路、时间复杂度、空间复杂度分析

  • 最新 Android 10 源码分析系列文章,了解系统源码,不仅有助于分析问题,在面试过程中,对我们也是非常有帮助的,仓库持续更新,欢迎前去查看 Android10-Source-Analysis

  • 整理和翻译一系列精选国外的技术文章,每篇文章都会有译者思考部分,对原文的更加深入的解读,仓库持续更新,欢迎前去查看 Technical-Article-Translation

  • 「为互联网人而设计,国内国外名站导航」涵括新闻、体育、生活、娱乐、设计、产品、运营、前端开发、Android 开发等等网址,欢迎前去查看 为互联网人而设计导航网站

感谢

感谢 Simple one-liner ViewBinding in Fragments and Activities with Kotlin 文章带来的思路,以及从 AnkoViewBindingDelegatearchitecture-components-samples 和 jetpack 等等开源库中学习到技巧