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

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)这个判断添加是怎么来的了 ,由编译器自动为我们生成而来。
  喜欢这篇文章的小伙伴,欢迎评论区留言,麻烦点个关注或收藏哦,您的支持就是小编创作的最大动力!

知名景区宣布关闭!上海人纷纷赶来打卡,网红店又开始人挤人去年年底,有公告称召稼楼景区于今年1月21日关闭要知道召稼楼的风格简单直接充满了本地特色的吃和买网红美食店可以一整天都排长队可以说是上海最闹猛的古镇了于是大家都着急去打卡就怕再也吃便便臭味大粘马桶,是怎么回事?提醒先别碰这2类食物谣零零计划参考资料1中国慢性便秘诊治指南(2013,武汉)J。胃肠病学,2013,18(10)605612。2王佩佩,罗雯,禹铮,李明玮。慢性便秘的研究进展J。中国全科医学,201胆不好,记住这6点,让胆更健康平常出现消化不良,很多朋友都一定认为是胃出了问题。但消化这一功能,其实还需要胆的协助。很多人因为不了解而忽视了他,甚至不知不觉中伤害了他,最终导致肝胆乃至胃肠的疾病出现。所以,生活文案丨20句适合元宵节发朋友圈的高级文案欢迎来到山月文案馆吖首先祝大家元宵快乐呀!赶紧的收藏马上发起来吧1灯与月依旧,人与人长久2为你花开满城,为你明灯三千。3取月色二两,揉碎星月,包成元宵4浮空明焰,千树琉璃水上灯莲,元宵节今年这些花灯一定没见过,灯火通明,光彩绚丽!元宵节也称灯节,闹花灯是元宵节的传统节日习俗,从古至今灯火之风盛行,并流传于后世。元宵节的花灯种类有很多,像龙灯荷花灯走马灯兔子灯花篮灯树地灯礼花灯等等。形态各异玲珑剔透,让人赏心元宵节赏灯热,释放旅游经济向好势头北京日报客户端记者潘福达今天是元宵节,多家旅游平台近日发布的元宵节旅游报告显示,今年春节至元宵节期间,传统文化元素出圈叠加异地流动政策的利好,包括自贡灯会在内的多地新春灯会热度持续春节假期,怒江福贡老姆登景区人气火爆人间烟火处,年味正浓时。春节假期,全国各地旅游景区人气火爆,游客出行热情高涨。近日,云南省怒江傈僳族自治州福贡县匹河怒族乡老姆登景区内人山人海热闹非凡,不少外地游客慕名而来,逛村寨元宵节点亮一盏面灯热热闹闹过完春节,最盼望的就是正月十五赶紧到来。这是我们小时候共同的心愿。那原因再简单不过白面馒头肉馅饺子的美好生活已经结束,红芋饭红芋馍的时代宣告回归,而正月十五那天却可以抓住春妖刀魏锐和武林风外籍功夫之王碰面,对手现场说出这番话!2月3日4日,河南卫视与唐山文旅集团联合举办的武林风将连续举办两场大赛。2月3日,将是一次中泰对决,由妖刀魏锐带领的中国战队对阵泰拳王子播求带领的泰国战队。其中,杨明位威阳等中国拳去董宇辉化导致股价暴跌,为何新包装上的方脸老师不见了?如果说新东方的灵魂是俞敏洪,那东方甄选的灵魂是董宇辉。不客气的说,东方甄选离开了董宇辉啥都不是。为啥很多粉丝都等着董宇辉直播的时候下单?一是对他表示支持,第二就是他的直播才能一直看怎一个惨字了得!年销量最低两位数这几个汽车品牌可能倒在2023年大浪淘沙,是车市不变的规律,车市发展越是成熟,马太效应越是明显。2022年,激烈的市场竞争中,一批曾经熟悉的汽车品牌相继告别中国市场,其中,包括广汽菲克广汽讴歌宝沃等品牌,跟中国车
当TVB女星遇到内地美人,佘诗曼次次都输,男人婆张延不输李若彤在当年香港娱乐圈的黄金时期,曾经流传过这样一句话,一流美女才能演香港电影,二三流美女只能去TVB演电视剧。比如拥有石破天惊美貌的大美人李嘉欣,当年拿了港姐冠军签约TVB以后,只演了同是毛毛球造型,贾静雯俏皮杨幂朝气,却拯救不了黄圣依的宽额头今朝春气寒,春雪来相伴!没想到已经阳春三月了,饭姐还能赏一波春雪。而借这次的春雪好景,饭姐也看到了不少美女的雪中大片。第一个看到的就是白鹿雪中跳舞的视频,能把舞蹈跳出搞笑风,白鹿也这4位女星个个错过走红机会,明明颜值演技佳,可偏偏各有难处倚天屠龙记之魔教教主续集一经上线,评论区全被王晶的眼光肿了吗刷屏。比中老年版武侠剧更辣眼的是周芷若那沟壑纵横的脸蛋,灵气全无,与小说里描写的形象完全无关,脸僵如石,更别提秀若芝兰了靠脸吃饭的女明星,美与丑全在造型师的一念之间,真是太惨了众所周知,娱乐圈的女明星们绝大多数都长得明眸皓齿,清秀可人。当她们的颜值和造型双双达到巅峰的时候,这就足以让无数男人垂涎,女人艳羡。可奈何娱乐圈是个鱼龙混杂的地方,总有一些审美奇葩同样是小个子,为什么别人的穿搭那么好看?差在哪了?作为一个小个子,你是不是常常懊恼为什么别人穿的衣服那么好看,到了自己身上就成了五大三粗?身高的限制确实给了我们的穿搭带来更多阻碍,腿短的情况下很容易横向加宽身材,看起来臃肿又显胖。高圆圆还是很好看,还是不太会演不知道大家还记不记得九年前的咱们结婚吧,播出时盛况空前,唯一让观众喊打喊杀的是导演,让高圆圆演恨嫁剩女!脑子是怎么想的?拍咱们结婚吧那年,高圆圆正在和赵又廷热恋,如今俩人结婚有娃,玩转MIUI13小部件,如何打造精致好看有趣的打工人时钟?包教包会大家好,我是Flashcer,MIUI玩机爱好者萌新小米粉,希望大家能多多关注今天Flashcer继续分享玩机技巧,这期关于精致好看又有趣的打工人时钟玩机技巧分享。MIUI13小部好看又得体的极简穿衣法,帮你省钱省时省精力后台回复书名一键免费阅读成为一颗星奇风岁月旅行人信札书店日记懒惰脑科学她们本文摘自普通力很长时间为人们所接受,不曾在这世间消失的东西。每当遇到这样的商品,总会想这里面一定有什么特别微胖女生怎么穿裙子才好看?记住这3个技巧,显瘦又气质裙子是每个女生都必备的一款时尚单品,不管是连衣裙还是半身裙,都能轻松塑造出女性的温柔淑女形象,而不少微胖女生面对好看的裙子时,总是望而却步,怕自己穿上裙子会显胖不好看。其实对微胖女妇产科普关于更年期,女性越早知道越好!更年期是女性进入老年期所必须经历的一个生理阶段,更年期的女性会经历一系列生理和心理上的改变。做好更年期的保健管理,促进更年期女性健康,延缓老年疾病的发生,为老年期健康打下基础。一正中国第一位女性首富,靠着白手起家,如今坐拥440亿身家成功的企业家有很多,而张茵只是其中的一位。这位出生在广东韶关的黑龙江人,虽然没有马云马化腾那么家喻户晓,但她单靠收破烂发家致富的能力很值得大家学习与借鉴。张茵用她的成功来让我们惊醒