【ZZ】bindable浅谈

本文深入探讨了Flex中Bindable元数据的应用与限制,通过实例介绍了如何使用Bindable元数据建立绑定关系,并解释了其工作原理及注意事项。
刚写完blog,拿出来分享一下。
来自http://gain-loss.org/

[Bindable]大概又是Flex用得最多的元数据了。刚开始用用确实好简单,效率真是没的说。不过这几天用着却碰到了些问题,我自己搜集了些资料,想着有必要在blog里总结一下吧。

啥是元数据(metadata)

知道就跳过吧。今天不晓得为什么livedoc.adobe.com这么慢,没办法,拿不到权威的解释了。我就按自己的理解随便解释一下:首先要明白元数据不是语法的一部分,而是专门给编译器用的,说白了是告诉编译器做某些事情,学过java之类的应该知道。那Bindable来讲,它的作用是告诉 flex编译器,给某些某些东西建立绑定关系,flex编译器会在编译过程中给AS(flex编译器就是把mxml编译成as,再编译到swf,也可能直接编译倒swf,我这里假设有as这么个环节)加一点事件发生和处理之类的代码,由此绑定的关系便建立了,如果我们用纯粹as3代码来写也是可以实现的,就是太太太麻烦。

啥是绑定

知道继续跳过。举个例子:给下面的public变量加上[Bindable]

[Bindable]
public var name:String = "";

作为一个public变量,肯定既可以被赋值,也能赋值给别的变量。绑定的作用就是,当name改变的时候(被赋值了),可能通知其它被name影响(赋值给它们)的变量发生改变。这里的“可能”就需要编译器来判断,这就是为什么元数据是给编译器用的原因了。在mxml里用{}的语法的地方就是绑定的对象,比如label={xxx.name},当name变化,label也跟着变化。这样,我们只是很简单的改变了name的值,由于有绑定,界面上的label也跟着自动变化了,爽吧。

能用在哪里

三个地方:类, 变量, getter/setter。是不是public没有关系,private的就只能给自家用呗。用在Class上就是简单的给所有的public属性(包括变量,getter/setter,普通方法)加上[Bindable],可是一般的方法不能用[Bindable]呀,于是一般就能看到flex给了个warning,直接无视。变量嘛就是上面讲的,很简单略掉。

用在只读,只写属性(getter/setter)上面

终于讲到关键地方了,因为getter和setter很像方法,用起来会有点不同。看看这个例子:

[Bindable]
private var content:Array = new Array();
[Bindable]
public function set _content(ct:String):void
{
content = ct.split(SEP);
}
[Bindable]
public function get _wholeText():String
{
if(content.length == 0)
{
return "";
}
else
{
var _w:String = "";
for(var i:int=0 ; i<content.length ; i++)
{
_w += content[i] + "\r\n";
}
return _w;
}
}

原来的设想是content绑定_wholeText,可它是不工作的。为什么?_wholeText太复杂了,被编译器排除在“可能”之外,编译器认为没有绑定关系,如果只是简单的return content,倒是可以的。我这里搜到了一些比较权威的解释。来自http://www.rubenswieringa.com/bl ... y-accessors-in-flex找到Ely Greenfield讲的。

Now keep in mind that there’s no way for the compiler to actually tell if the value of a property get function would be different if called, short of doing an extensive code flow analysis of the get function, identifying all the inputs that might be affecting the value of the get function (i.e., member fields, statics, globals that are used in the get function and in any methods, global functions, closures, etc) it might call, and setting up watchers on every one of those to trigger the binding when any of them change. That’s prohibitively difficult, and expensive to do. So the compiler doesn’t try.

Instead when you put [Bindable] on a get/set property, the compiler makes it bindable with a little creative rewriting that allows the framework to watch the get function, and dispatch a change event when the get function is triggered. This means that automatic bindable properties don’t work when the get function is computed from multiple values, or when you change its value by setting a backing field, rather than using the set function.

It _also_ means that if you have no set function, we can pretty much guarantee that there’s no way automatically bindable get properties will be triggered. a read only propeerty is, to the compiler, completely opaque…at the moment, it has no idea where that value is coming from, and hence will never be able to ‘automatically’ trigger the binding.

说白了就是为了降低复杂度和提高效率,复杂情况的getter会被忽略。如何解决?可以手动建立绑定,即[Bindable("eventName")]。把代码改成这样:

[Bindable]
private var content:Array = new Array();
[Bindable]
public function set _content(ct:String):void
{
content = ct.split(SEP);
this.dispatchEvent(new Event("_contectChanged"));
}
[Bindable("_contectChanged")]
public function get _wholeText():String
{
if(content.length == 0)
{
return "";
}
else
{
var _w:String = "";
for(var i:int=0 ; i<content.length ; i++)
{
_w += content[i] + "\r\n";
}
return _w;
}
}

这样就避免了编译器去自动识别。自己加上绑定关系,当_content被赋值,发出_contentChanged事件,通知所有被绑定的getter方法执行一遍。这也说明了,绑定不过是事件游戏而已,flex为用户隐藏了很多底层算法。
<think>好的,我现在需要帮助用户了解如何使用Android DataBinding。根据用户提供的引用内容,我需要整理一个结构清晰的教程。首先,我要确定DataBinding的基本配置步骤,因为这是开始使用的前提。然后,布局文件的修改是关键,需要解释如何将传统布局转换为DataBinding支持的格式。接下来,数据绑定的部分,用户可能需要知道如何创建数据模型并将其与UI绑定,引用中的User类示例和BindingAdapter的使用都是重点。此外,用户可能对在Activity和Fragment中的不同用法感兴趣,比如在Activity中使用DataBindingUtil.setContentView,而在Fragment中使用inflate方法。我还需要提到数据绑定的优势,比如减少样板代码,以及处理复杂数据的方法,比如使用@BindingAdapter自定义属性。最后,生成相关问题可以帮助用户深入理解,比如性能优化或与LiveData的结合。需要确保所有步骤都符合引用内容,并且语法正确,使用中文回答,行内公式用$...$,独立公式用$$...$$,不过在这个问题中可能公式较少,但要注意LaTeX的正确使用。检查是否有遗漏的步骤,例如启用DataBinding的Gradle配置,绑定变量的设置,以及事件处理的方法。确保每个部分都有对应的引用标注,比如在Activity和Fragment中的用法分别引用[^2]和[^1]。最后,生成的相关问题要覆盖用户可能感兴趣的扩展方向,如性能、优化、应用场景等。</think>### Android DataBinding 使用教程 #### 1. **启用DataBinding** 在模块的$build.gradle$文件中添加配置: ```groovy android { ... dataBinding { enabled = true } } ``` 同步项目后,系统会自动生成与布局文件对应的绑定类。 #### 2. **修改布局文件** 将传统XML转换为DataBinding格式: ```xml <!-- activity_main.xml --> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="com.example.User" /> </data> <LinearLayout...> <TextView android:text="@{user.name}" // 直接绑定变量 .../> <ImageView app:imageUrl="@{user.avatarUrl}" // 自定义属性绑定 .../> </LinearLayout> </layout> ``` 布局根标签需改为$<layout>$,并通过$<data>$定义变量[^3]。 #### 3. **数据绑定实现** - **数据模型类**(例如$User$)需使用可观察机制(如$BaseObservable$或$LiveData$): ```java public class User extends BaseObservable { private String name; @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); // 触发UI更新 } } ``` - **在Activity中绑定数据**: ```java ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); User user = new User(); user.setName("John Doe"); binding.setUser(user); // 关键绑定语句 ``` - **在Fragment/Adapter中使用**: ```java ListItemBinding binding = DataBindingUtil.inflate( LayoutInflater.from(context), R.layout.list_item, parent, false ); binding.setVariable(BR.item, dataItem); // BR.item对应布局中定义的变量名[^1] ``` #### 4. **处理复杂绑定** - **自定义属性**:通过$@BindingAdapter$实现网络图片加载等逻辑: ```java @BindingAdapter("imageUrl") public static void bindImageUrl(ImageView view, String url) { Glide.with(view).load(url).into(view); // 使用第三方库加载图片[^4] } ``` - **事件绑定**:在布局中直接绑定点击事件: ```xml <Button android:onClick="@{() -> viewModel.onButtonClick()}" .../> ``` #### 5. **优势与注意事项** - **优势**:减少$findViewById$调用,UI更新自动化,代码可读性提升[^3] - **注意**:避免在布局中编写复杂逻辑,建议与ViewModel或Presenter模式结合
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值