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

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

重磅!现代汽车宣布投资SoC设计企业如果有谁能给我芯片,我可以请他喝酒,去年12月,小鹏汽车董事长兼CEO何小鹏在出席央视对话挑战者栏目时候提到,自己最焦虑的就是供应链问题,经常打飞的请人喝酒找芯片。在他看来,芯片的2022世界人工智能大会将展现人工智能及元宇宙领域硬核新科技乔翔见习记者李梦扬中国证券报中证网中证网讯(记者乔翔见习记者李梦扬)8月26日上午,上海市政府新闻发布厅举行市政府新闻发布会,介绍2022世界人工智能大会筹备等有关情况。上海市经济本质安全科技赋能新一代固态电池储能系统即将发布能源新闻网讯双碳目标下,储能正成为多个国家能源转型进程中的关键技术之一。聚焦国内,以2021年为起点中国储能市场进入真正意义上的规模化发展。据中关村储能产业技术联盟(CNESA)统iPhone14或成印度制造!2000多家外企撤退,苹果却偏向虎山行iPhone14即将上市之际,据美媒本月23日相关报道透露,苹果正计划准备在印度生产新机,据悉,印度第一批新机生产可能在今年10月到11月完成。可是长久以来,苹果大部分生产链都分布iQOO发布Z6系列千元价位新机,主打性能续航新京报贝壳财经讯(记者许诺)8月25日,vivo旗下品牌iQOO举办线上发布会,发布了Z6系列新机。该系列以80W闪充6400万像素OIS三摄6000mAh电池等配置为卖点,定位在华为的管理模式,为什么中小企业都争先恐后的学习?值得一看作者邓斌文稿整理刘浩本文由销售与管理战略合作伙伴人民邮电出版社授权发布30余年间,华为从一个地方小企业成长为行业全球领先企业,成为中国企业在世界的标签,靠的正是它不断坚持的核心价值逝者稻盛和夫想活下去,请付出不亚于任何人的努力日本经营之圣稻盛和夫,于8月24日去世,享年90岁,一代商业传奇就此落幕。他52岁前先后创立两家世界500强企业,在78岁临危受命,用1年多的时间将濒临倒闭的日航实现扭亏为盈,并一高群耀爱上不确定性,是你现在最值得做的事独家战胜焦虑的方法是,每个人都要有定力,也就是战略思维。文高群耀编辑姚赟头图来源视觉中国作者简介高群耀博士(JackQ。Gao,Ph。D),现任移动电影院创始合伙人兼首席执行官。先后毕伯利英超可效仿美国办全明星赛MLB两天就赚了两亿近日,切尔西老板伯利在接受SALTNY的采访时提议称,英超联赛可以效仿美国体育那样举办南北全明星对抗赛,并举例称MLB(美国职业棒球联盟)就从全明星赛中赚取了丰厚的利润。伯利表示我6秒小视频!完了!NBA史上第一个被封杀的状元从天堂到地狱,最快只要多久?不同的人有不同的答案,森林狼的状元秀爱德华兹大概会回答你3个月,但实际上可能只需要6秒。3个月前,爱德华兹还是一个超新星,他帮助森林狼重返季后赛。尽管只美国蓝色起源公司新谢泼德火箭发射失败坠毁,太空舱成功逃逸(观察者网讯)看来我们今天(9月12日)的飞行遇到了异常。9月12日,贝索斯旗下太空公司蓝色起源的新谢泼德火箭在执行一次非载人任务时发生故障,在得克萨斯州指定区域坠毁。这是蓝色起源
iPhone15消息泄露!灵动岛成全系标配,售价又得翻一番?iphone14系列手机上市以来,就一直被各种嫌弃,其口碑也不如以往那么好。甚至是坑苦了一众黄牛,被戏称为黄牛克星。但是,即便如此iphone14系列手机的销量依然是高歌猛进。毕竟同样是赵本山的女儿,赵玉芳和球球却活成了完全相反的样子前言赵本山有过两段婚姻,生下了4个子女。没成名以前和葛淑珍结婚,生下了大女儿赵玉芳和多病早逝的儿子赵铁蛋,12岁就夭折了。成名后和葛淑珍离婚,女儿跟着前妻他净身出户。一年之后他又娶中军摩派到中天摩派,骗局还是那个骗局,换了个名字前不久,防骗小视野转发报道过一篇名为换部手机就能躺赚?中军通信的启屏广告手机推广模式遭质疑!的文章。文章曝光后收到了来自全国各地粉丝的点赞和转发,聚集了大量的关注。原本曝光的目的就为生男孩,她喂孕妇吃转胎丸,孩子却惨成畸形双性人农村的一处小院子里,一个小腹微微隆起的女人正看着眼前盛着不明液体的碗有些为难。孕妇看了看丈夫,他对母亲的决定似乎非常支持,并没有拦着的意思。妈,我听人说这东西对孩子不一定好,万一造珠海航展今日开幕!大男孩的圆梦之地第十四届中国国际航空航天博览会将于2022年11月8日至13日在广东珠海国际航展中心举行,集中展示我国航空航天和国防科技领域的尖端技术及创新突破。精彩内容一睹为快展览亮点陆空一体演乡村振兴看安徽丨安徽霍山筑巢引得凤凰栖,南庄老茶发新芽央广网霍山5月16日消息(记者徐鹏通讯员陈波)春生夏长,万物繁茂。时过立夏,霍山县漫水河镇南庄村一处高山茶园里,喝饱了初夏雨水的茶叶翠绿茁壮。黄大茶是立夏前后黄芽采摘结束,茶叶长到北京加强快递外卖农贸市场等重点行业重点人群核酸筛查北京市卫健委提醒要坚持动态清零总方针不动摇,坚定必胜信心,压实四方责任,认真落实各项防控措施,做好风险人员排查,加强员工管理,建立人员台账,掌握员工动态,严格落实测温验码健康监测核2020年,福建女子丧夫后用胚胎做试管婴儿被拒,医院须丈夫同意前言常言道不孝有三,无后为大,娶妻生子,延续香火,是我们中国人的传统认知。特别是作为一个女人来说,更是渴望做妈妈的,但是世事无常,现实生活中有很多夫妻却被不孕不育所困扰。不过随着医张亮14岁儿子被曝早恋,和漂亮女友亲吻互动,张亮发长文回应2013年,一档亲子真人秀爸爸去哪儿热播,而节目中,张亮厨艺精湛情商高,儿子天天可爱懂事,父子俩以抢眼的表现,受到了无数观众的喜欢。当年张亮儿子天天(张悦轩)才6岁,一转眼如今已经美丽风景线是做梦!佩洛西再发涉港错误言论,赵立坚犀利回应近日,美国众议院议长佩洛西在华盛顿邮报发表涉港错误言论,无理攻击中国的涉港政策,大言不惭地抹黑中国有关香港高度自治的承诺,对此中方也给出了犀利回应。5月16日,中国外交部发言人赵立酸汤鱼片比酸菜鱼好吃多了,酸甜开胃,鲜香可口,连汤汁都好喝酸汤鱼片比酸菜鱼好吃多了,酸甜开胃,鲜香可口,连汤汁都好喝!酸汤鱼片,鱼肉鲜嫩,汤汁酸甜鲜香,比酸菜鱼好吃多了,很适合广东人。作为广东人,我不太喜欢吃辣椒,但是喜欢吃酸,酸菜鱼就是