范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Jetpack之DataBinding绑定布局文件是怎样实现的?

  dataBinding的实现原理是什么?dataBinding是怎么进行数据双向驱动的?
  时间从来不语,却回答了所有。——致自己
  本文从定义,用法,原理分析,由浅到深对DataBinding的实现原理进行挖掘,方便各位读者理解。篇幅较长,请耐心阅读。定义:使用声明形式将布局中的界面组件绑定到应用中的数据源。数据的改变直接驱动UI的变化。 视图绑定:  该模块的  build.gradle 文件中将  dataBinding 构建选项设置为  true。android {         ...         //第一种         dataBinding {             enabled = true         }         //第二种          dataBinding.enabled = true         //第三种         buildFeatures {         viewBinding true         }     }      将xml布局中的根布局改成layout<?xml version="1.0" encoding="utf-8"?>                       在Activity中使用视图绑定 override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         //第一种 直接绑定         val binding: ActivityMainBinding = DataBindingUtil.setContentView(                 this, R.layout.activity_main)         //第二种 可以使用 LayoutInflater 获取视图          val binding: ActivityMainBinding = ActivityMainBinding.inflate          (getLayoutInflater())          setContentView(binding.root)     }  在Fragment中使用视图绑定
  如果要在  Fragment、 ListView 或  RecyclerView 适配器中使用数据绑定项,使用绑定类或  DataBindingUtil 类的  inflate() 方法,如以下代码示例所示:     val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)     // or     val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)
  3 数据双向绑定
  DataBinding除了可以进行布局绑定之外,还可以对布局view进行数据绑定。<?xml version="1.0" encoding="utf-8"?>                                                                              
  在根标签layout中添加一个data标签,name为数据bean的别名,type为数据bean的全类名。然后通过给TextView的text属性,布局中的表达式使用" @{}"语法写入特性属性中 进行数据绑定。android:text="@{user.firstName}",。在这里, TextView 文本被设置为  user 变量的  firstName 属性。
  数据对象User  data class User(val firstName,val lastName)
  然后再Activity中,通过binding.user = User("","")将user变量绑定到布局视图上。     override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)          val binding: ActivityMainBinding = DataBindingUtil.setContentView(                 this, R.layout.activity_main)          binding.user = User("Test", "User")     }
  这样我们就完成了一个简单是数据到布局视图上的绑定,如果我们修改了user中的某个属性值,视图也会更新吗?我们接着往下看。
  Databinding不仅提供了绑定视图的功能,还提供了动态更新的功能。通过使用可观察的数据对象,通知布局自动更新。    class User {         val firstName = ObservableField()         val lastName = ObservableField()         val age = ObservableInt()     }
  首先我们将User对象中的数据定义为可观察的对象属性,当我们修改其中某个变量值得时候,会主动通知布局更新。除此之外还有没有其他办法实现?这个当然有,我们接着往下看。    class User : BaseObservable() {          @get:Bindable         var firstName: String = ""             set(value) {                 field = value                 notifyPropertyChanged(BR.firstName)             }          @get:Bindable         var lastName: String = ""             set(value) {                 field = value                 notifyPropertyChanged(BR.lastName)             }     }
  通过实现Observable接口将User对象变成一个可观察的对象,以便它们接收有关可观察对象的属性更改的通知。 Observable 接口具有添加和移除监听器的机制,但何时发送通知必须由您决定。为便于开发,数据绑定库提供了用于实现监听器注册机制的  BaseObservable 类。实现  BaseObservable 的数据类负责在属性更改时发出通知。具体操作过程是向 getter 分配  Bindable 注释,然后在 setter 中调用  notifyPropertyChanged() 方法,如以下示例所示:     class User : BaseObservable() {          @get:Bindable         var firstName: String = ""             set(value) {                 field = value                 notifyPropertyChanged(BR.firstName)             }          @get:Bindable         var lastName: String = ""             set(value) {                 field = value                 notifyPropertyChanged(BR.lastName)             }     }
  数据绑定在模块包中生成一个名为  BR 地类,该类包含用于数据绑定的资源的 ID。在编译期间, Bindable 注释会在  BR 类文件中生成一个条目。如果数据类的基类无法更改, Observable 接口可以使用  PropertyChangeRegistry 对象实现,以便有效地注册和通知监听器。
  4 原理分析
  我们首先来看一下DataBindingUtil是如何绑定xml布局的:DataBindingUtil.setContentView(this,  R.layout.activity_main ) public static  T setContentView(@NonNull Activity activity,             int layoutId, @Nullable DataBindingComponent bindingComponent) {         //调用当前activity的setContentView方法         activity.setContentView(layoutId);         View decorView = activity.getWindow().getDecorView();         //通过findViewById获取根布局         ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);         return bindToAddedViews(bindingComponent, contentView, 0, layoutId);     }  private static  T bindToAddedViews(DataBindingComponent component,             ViewGroup parent, int startChildren, int layoutId) {         //获取子view个数         final int endChildren = parent.getChildCount();         //添加了多少个view         final int childrenAdded = endChildren - startChildren;         //当只有一个子view时,直接获取ziview         if (childrenAdded == 1) {             final View childView = parent.getChildAt(endChildren - 1);             return bind(component, childView, layoutId);         } else {             //当数量大于1个时,创建view数组用来接收子view             final View[] children = new View[childrenAdded];             for (int i = 0; i < childrenAdded; i++) {                 children[i] = parent.getChildAt(i + startChildren);             }             return bind(component, children, layoutId);         }     }
  从源码中可以看出不管是只有一个子View还是多个子View,最终都是调用bind()方法,我们接着往下看。   static  T bind(DataBindingComponent bindingComponent, View[] roots,             int layoutId) {         return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId);     }
  通过调用bind方法,我们看到sMapper.getDataBinder 返回一个DataBinding对象,那这个getDataBinder方法是怎么返回的呢,我们点进去发现调用到DataBinderMapper.getDataBinder,DataBindingMapper是个抽象类,那我们只能从其子类DataBinderMapperImpl入手。public ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {         int localizedLayoutId = INTERNAL_LAYOUT_ID_LOOKUP.get(layoutId);         if (localizedLayoutId > 0) { //获取布局             Object tag = view.getTag();             if (tag == null) {                 throw new RuntimeException("view must have a tag");             }              switch (localizedLayoutId) {                 case 1:                     //如果tag与这个标记相等 就new一个ActivityMainBindingImpl 返回                     if ("layout/activity_main_0".equals(tag)) {                         return new ActivityMainBindingImpl(component, view);                     }                      throw new IllegalArgumentException("The tag for activity_main is invalid. Received: " + tag);             }         }          return null;     }
  从DataBinderMapperImpl的getDataBinder中,我们终于看到了ActivityMainBindingImpl被创建,ActivityMainBindingImpl是ActivityMainBinding的实现类,至此我们终于知道val  activityMainBinding = DataBindingUtil.setContentView(this,  R.layout.activity_main )是如果被创建返回的了。
  看到这里很多人有疑问了? "layout/activity_main_0".equals(tag) 这判断是怎么来的,明明自己没有在布局中没有设置tag标签,那这个tag是从哪来的?带着这个疑问我们进一步深入研究一下。首先我们要知道Databinding是基于APT技术动态生成的,比如上面的ActivityMainBindingImpl等代码都是通过编译自动生成。那么有没有一种可能 这个tag标签也是自动生成插入的。我们往下看。
  我们找到编译后的activity_main-layout.xml文件,看一下编译器为我们做了哪些工作?<?xml version="1.0" encoding="utf-8" standalone="yes"?>                //编译器自动为我们插入一个tag                                                                                               
  我们从编译后的布局文件中可以看到,编译器在第八行 自动为我们插入了一个tag="layout/activity_main_0" 标签。用来代替我们在layout根标签的布局文件。至此我们知道了"layout/activity_main_0".equals(tag)这个判断添加是怎么来的了 ,由编译器自动为我们生成而来。
  喜欢这篇文章的小伙伴,欢迎评论区留言,麻烦点个关注或收藏哦,您的支持就是小编创作的最大动力!

有一种豁然,叫转弯但凡正常的人,都是愿意活出一种明白和豁然的,希望自己不被云遮,不遭雾绕,而是头脑清醒,眼睛明亮,道路顺畅,人生圆满。但在现实中,总有一些人看起来似乎有想法有抱负,也似乎很勤奋很执着百吃不厌的红豆面包,香甜暄软眨眼就吃没了,意犹未尽,下次多做秋日生活打卡季百吃不厌的红豆面包,香甜暄软眨眼就吃没了,意犹未尽,下次多做好久没做小面包了,今天翻出来一个6连模,正好手上还有打开的蜜红豆,想了一下,就鼓捣出来今天的主角红豆面包。炸丸子时,加面粉和淀粉是大错,教你一招,这样做外酥里嫩,真香生活没有彩排,美食没有美颜。大家好,今天给大家分享一道好吃的家庭般丸子。丸子,大家都是非常的喜欢吃,日常生活中经常会吃到,但是更多的时候都是在外面买着吃,今天我们给大家分享丸子的好说话上面的那些禁忌和思考我最近感触颇多,加上过去我因为口误,或故意,或无意,伤及他人,要么就是殃及本身,轻则尴尬,重则惹人怒目而视。这一篇,就是我的思考,而尤为重要的是其中说话的禁忌。1。话切忌太满2。话个人认为的现代社会现在的社会,贫富差距越来越大,社会越来越不公平。但是很多人都明白,这是迟早的事情,贫富差距越大,人民内部矛盾越大,社会就越不稳定。社会的隔阂就越大,不公平的情况也就越严重,环境越恶去年我国社会消费品零售总额达44。1万亿元消费主引擎动力强劲原标题2021年我国社会消费品零售总额达44。1万亿元,比2012年增长1。1倍消费主引擎动力强劲数据来源商务部制图蔡华伟北京市朝阳区三里屯太古里,不少时尚品牌在这里开设北京首店乃秋天了,包菜这样吃才过瘾,我家2天就忍不住做一次,上桌扫光秋天了,包菜这样吃才过瘾,我家2天就忍不住做一次,上桌扫光。包菜的水分含量大约有90,维生素C的含量比白菜高出一倍左右,包菜中的叶酸含量也比较高,还有多种微量元素,反正就是好处多!蒸红薯好吃有技巧,别直接蒸,牢记3点,个个流糖汁,比烤的还香蒸红薯好吃有技巧,别直接蒸,牢记3点,个个流糖汁,比烤的还香秋季,最不可错过的美食就是红薯了。红薯是一种粗粮,可以代替大米白面,营养价值很高,被誉为长寿食品,经常吃可以延年益寿,强维嘉再出事?快乐家族曾经有多风光,如今的处境就有多让人唏嘘2021年,老牌综艺快乐大本营停播!这档1997年在湖南台首播为上星筹备的节目,彼时已经播出了整整24年。这24年来,迎来送往了无数的艺人明星。很多人在这里成名,在这里宣传戏他们歌linux常用命令之查看系统信息1。arch显示机器的处理器架构2。unamem显示处理器架构3。unamer显示正在使用的内核版本4。hdparmdevsda显示硬盘的相关设置5。catproccpuinfo显系统化区块链基础知识什么是区块链(通俗易懂)区块链就是分布式账本技术大家觉得区块链是什么?或者在你脑海里面提到区块链的时候,你是否觉得自己真的知道区块链是什么?我想可能很多人还是没有太多概念。有些币圈的人多多少少可能都有些概
我国四大能源生命通道之中缅油气管道为破解我国能源运输通道的马六甲困局,我国采取的全球战略有哪些?众所周知的有东北西北西南和东部沿海的海上油气能源通道。东北能源通道由中俄油气管道组成,可年投产输送原油3000万吨天然氯化钾巨头藏格矿业前三季净利润预增逾4倍,超41亿元藏格矿业视觉中国资料图10月13日,氯化钾巨头藏格矿业股份有限公司(下称藏格矿业,000408)发布三季度业绩预告,前三季度净利润41。3亿元至42。3亿元,同比增长400。55至欧冠稳定的皇仁城,惊喜的拿波里,意外的米兰尤文马竞本赛季的欧冠已经战罢4轮,有的球队已提前出线,有些球队深陷泥泞,有些球队强势反弹,有些球队逐渐失去主动权,来看看一起看看这些球队都有谁!一如既往稳定的豪门要数本赛季欧冠最稳定的3家陕西唯一没有通高速的县,火车也是绕道而走,面积却占西安的30我在头条搞创作第二期陕西大家都不陌生,有赏不完的文物古迹,品不完的美食小吃,听不完的历史故事。按地形地貌分为陕南秦岭山脉,陕北黄土高坡,关中渭河平原。以前的陕西名不经传,现在的陕西孙杨张豆豆结婚再添新证据!2人婚戒不离手,婆媳2人还一起遛狗随着孙杨世界纪录证书的寄回,他在一次成为了热点人物,时时刻刻在网友的观察视线里。近日在社交媒体上我们发现了一组照片,张豆豆再次被拍到与婆婆两人遛狗,照片中的两人气氛十分的和谐,整个CBA朱旭航四记三分,范汇鎏10分正负值最高,周鹏11分遗憾落败深圳队和新疆队两队在第二轮常规赛相遇,第一轮比赛两队都各自战胜强敌,对手都是季后赛级别的强队。这一场较量也将碰撞出更加激烈的火花。深圳队大外援萨林杰非常兴奋,在现场跳起了舞蹈。上半华为P50mate50系列总体配置预览华为P50是华为公司出品的一款手机,于2021年7月29日发布。该手机采用6。5英寸OLED屏幕,支持80倍变焦。华为P50搭载高通骁龙8884G处理器,采用6。5英寸vivoX90系列爆料信息整理联发科盘绕X90Pro,新增超大杯Pro(vivoX70Pro)根据内部行业人士爆料信息显示vivoX90系列定档11月就要发布了,按照生产流程从EVTDVTPVTMP显示,目前X90系列已经在投产了,相关参数也得到了了天玑1080处理器发布荣耀80系列将搭载此芯片,加持百瓦快充10月11日,联发科今天发布了新款中档芯片天玑1080。这款芯片最大的卖点是它的性能和影像功能。采用了台积电6nm工艺,搭载八核CPU2个ARMCortexA78核心,频率高达2。喜迎二十大系列有声海报自主创芯让飞腾展翅腾飞为喜迎党的二十大胜利召开,津云新媒体策划推出系列有声海报,每期邀请一位讲述者,解读习近平新时代中国特色社会主义思想在津沽大地的生动实践,憧憬天津全面建设社会主义现代化大都市的美好未你几点起,就是什么命曾有人问怎样才能把生活过成自己想要的样子?点赞最高的回答是做一个对自己有要求的人就可以了。要知道,一个人吃不了自律的苦,终究还是会吃平庸的苦。而一个人未来的样子,就藏在他对待清晨的