使用 DataBinding 库绑定事件
Posted
技术标签:
【中文标题】使用 DataBinding 库绑定事件【英文标题】:Using DataBinding library for binding events 【发布时间】:2015-11-04 20:48:23 【问题描述】:我正在尝试使用 android M 附带的 DataBinding 库 将事件与 xml 中的视图绑定。我正在遵循 Android Developers 中的示例并逐步实现。对于视图的属性,如可见性,文本其工作正常,但如果我尝试与 onclick 绑定,它不会按预期工作。这是我到目前为止尝试过的示例代码:
<data>
<import type="android.view.View"/>
<variable name="user" type="com.example.databinding.User"/>
<variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>
<TextView
android:layout_
android:layout_
android:text="@user.firstName"
android:visibility="@user.isFriend ? View.VISIBLE : View.GONE" />
<Button
android:layout_
android:layout_
android:text="Click Me"
android:id="@+id/button"
android:layout_gravity="left"
android:onClick="@handlers.onClickFriend"/>
主要活动:
public class MainActivity extends AppCompatActivity
User user;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
ActivityMainBinding binding =
DataBindingUtil.setContentView(this,R.layout.activity_main);
user = new User("Pankaj","Kumar",true,true);
binding.setUser(user);
我的处理程序:
public class MyHandlers
public void onClickFriend(View view)
Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
public void onClickEnemy(View view)
Log.i(MyHandlers.class.getSimpleName(),"Now Enemy");
我只编写了必需的代码以提高可读性。有人可以帮我解决这个问题。
【问题讨论】:
【参考方案1】:我认为您还需要绑定handlers
,可能在onCreate
中是这样的:
MyHandlers handlers = new MyHandlers();
binding.setHandlers(handlers);
【讨论】:
是的,如果您将 Activity 类用作处理程序,那么您只需要这样做:binding.setHandlers(this);
如果你有许多相同的动作,你可以使用这个库来简单起见 - github.com/drstranges/ActionHandler
@dorsz +100 给你!我搜索了好几个小时!
如果您正在使用演示者,演示者也是如此
这太棒了!我希望文档能更好地概述这一点!感谢您的精彩回答!【参考方案2】:
不必创建单独的类MyHandlers
并调用setHandlers
来处理android:onClick
。您可以使用方法:public void onClickFriend(View view)
和 public void onClickEnemy(View view)
in MainActivity
。
活动视图:
public class MainActivity extends AppCompatActivity
User user;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
ActivityMainBinding binding =
DataBindingUtil.setContentView(this, R.layout.activity_main);
user = new User("Pankaj", "Kumar", true, true);
binding.setUser(user);
public void onClickFriend(View view)
Log.i(MyHandlers.class.getSimpleName(), "Now Friend");
public void onClickEnemy(View view)
Log.i(MyHandlers.class.getSimpleName(), "Now Enemy");
一个布局:
<data>
<import type="android.view.View"/>
<variable name="user" type="com.example.databinding.User"/>
</data>
<TextView
android:layout_
android:layout_
android:text="@user.firstName"
android:visibility="@user.isFriend ? View.VISIBLE : View.GONE" />
<Button
android:layout_
android:layout_
android:text="Click Me"
android:id="@+id/button"
android:layout_gravity="left"
android:onClick="@onClickFriend"/>
看一下为 MVVM 模式使用数据绑定库的示例:http://cases.azoft.com/mvvm-android-data-binding
【讨论】:
好吧android:onClick="@onClickFriend"
没用,但android:onClick="onClickFriend"
正常工作..
这几乎是真的。你可以使用你的Activity作为handler,layout中的onClick类似于android:onClick="@handlers::onClickFriend"
,但是你需要在Activity中绑定handler,像这样:binding.setHandlers(this);
嗨,你知道如何处理onlongclick
事件吗?【参考方案3】:
如果你要使用你的activity,不妨把自动绑定的context
对象替换掉,不然就浪费空间了。
生成一个名为 context 的特殊变量,用于绑定 根据需要表达。 context 的值是来自 根视图的 getContext()。上下文变量将被覆盖 具有该名称的显式变量声明。
binding.setContext(this);
和
<variable name="context" type="com.example.MyActivity"/>
请注意,如果您只使用纯字符串onClick="someFunc"
,那根本就不是数据绑定功能。这是一个较旧的功能,它使用一点反射来查找上下文中的方法。
【讨论】:
【参考方案4】:在你的 xml 中使用这种格式:
android:onClick="@handlers::onClickFriend"
注意::
,不用担心xml编辑器中的红线,因为目前这是为Android Studio xml编辑器打开的bug。
handlers
是数据标签中的变量:
<data>
<variable name="handlers" type="com.example.databinding.MyHandlers"/>
</data>
onClickFriend
是你的方法:
public class MyHandlers
public void onClickFriend(View view)
Log.i(MyHandlers.class.getSimpleName(),"Now Friend");
添加
对于 xml 中的句柄 onLongClick
添加:
android:onLongClick="@handlers::onLongClickFriend"
并在您的 ViewModel 类中添加 onLongClickFriend
方法:
public class MyHandlers
public boolean onLongClickFriend(View view)
Log.i(MyHandlers.class.getSimpleName(),"Long clicked Friend");
return true;
添加
如果需要显示toast消息,可以使用interface(更好的变体),或者在构造中传递MyHandlers
类中的context
:
public class MyHandlers
public boolean onLongClickFriend(View view)
Toast.makeText(view.getContext(), "On Long Click Listener", Toast.LENGTH_SHORT).show();
return true;
【讨论】:
嗨,你知道如何处理onlongclick
事件吗?
它没有用。无法编译项目。 Unknown attribute android:onLongClick
.
对不起,尝试将void
改成boolean
这样的方法:public boolean onLongClickFriend(View view)
,最后加上return true;
。
@walkmn 如何在 onClickFriend 方法中显示 toast 或传递上下文
我们可以使用view.getContext()
方法在每个方法中获取context
,因此无需使用构造函数传递它。【参考方案5】:
你应该这样做
android:onClick="@() -> handlers.onClickFriend()"
【讨论】:
您的意思是android:onClick="@(view) -> handlers.onClickFriend"
,否则 lambda 将与 onClick 事件的签名不匹配。
@AymenDaoudi 更正确应该是android:onClick="@(view) -> handlers.onClickFriend()"
唯一对我有用的方法来自@AlekseyMasny。谢了!
() -> function()
语法完全有效。请查看文档:developer.android.com/topic/libraries/data-binding/…【参考方案6】:
我发布此消息是因为我遇到过发生这种情况的其他情况。如果您有两个引用布局文件的活动,一个定义了 onclick 事件,而另一个定义了 onclick 事件,那么您在定义事件的活动中却没有收到相同的警告,而且奇怪的是。
要检查这一点,我建议在布局名称上通过right clicking
查找布局文件的用法,然后按find references
。不要忘记在事后重建应用程序。
【讨论】:
【参考方案7】:我发布此内容只是为了涵盖实现此目的的两种方式。 1.通过Listener绑定 2.按方法参考
布局:
<layout...>
<data>
<variable
name="handlers"
type="com.example.databinding.MyPresenter" />
<variable name="user" type="com.example.databinding.User"/>
</data>
<LinearLayout
android:layout_
android:layout_>
<Button
android:layout_
android:layout_
android:layout_marginTop="32dp"
android:text="Using Listener Binding"
android:onClick="@() -> handlers.onLisClick(user)"/>
<Button
android:layout_
android:layout_
android:layout_marginTop="32dp"
android:text="Using Method Ref"
android:onClick="@handlers::onButtonClicked"/>
</LinearLayout>
</layout>
活动:
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
ActivityMainBinding binding =
DataBindingUtil.setContentView(this, R.layout.activity_main);
MyPresenter presenter = new MyPresenter();
User user = new User("Alex","RJ")
binding.setUser(user);
binding.setHandlers(presenter);
我的演示者:
public class MyPresenter
//using listener binding
public void onLisClick(User user)
//do something..
//using method reference
public void onButtonClicked(View view)
// do something
注意: 1.在使用方法引用时,方法签名应该与您为任何其他 onClick 方法编写的相同,即 public 和 View 作为参数。
2.在使用监听器绑定的同时,您还可以根据需要直接传递对象并执行任何操作。
【讨论】:
【参考方案8】:设置点击的多种方式
将处理程序传递给绑定。
ActivityMainBinding 绑定 = DataBindingUtil.setContentView(this,R.layout.activity_main); 处理程序处理程序 = 新处理程序(); binding.setHandler(handler);
设置点击次数(使用以下任何一种)
android:onClick="@handler::onClickMethodReference"
或
android:onClick="@handler.onClickMethodReference"
或
android:onClick="@() -> handler.onClickLamda()"
或
android:onClick="@(v) -> handler.onClickLamdaWithView(v)"
或
android:onClick="@() -> handler.onClickLamdaWithView(model)"
请参阅 Handler 类了解。
public class Handler
public void onClickMethodReference(View view)
//
public void onClickLamda()
//
public void onClickLamdaWithView(View view)
//
public void onClickLamdaWithObject(Model model)
//
注意
当您具有与属性 onClick 相同的参数时,您可以使用 方法参考 (::)。 您可以传递任何对象,例如onClickLamdaWithObject
示例。
如果您需要传递View
对象,则只需使用(v)->
表达式即可。
进一步阅读
https://developer.android.com/topic/libraries/data-binding/expressions
【讨论】:
这是一个很好的答案。请注意,只有带箭头符号的底部三个是唯一允许您从 xml Ctrl-跳转到处理程序中的代码的代码(截至 3 月 19 日)【参考方案9】:对于那些无法处理长点击事件的人:
首先在布局中创建一个带有 id 的视图。
<data>
<variable
name="tempDesc"
type="String" />
<variable
name="activity"
type="com.naruto.trangoapp.MainActivity" />
</data>
<TextView
android:id="@+id/textView"
android:layout_
android:layout_
android:onClick="@(view) -> activity.changeDescText(view)"
android:text="@tempDesc" />
在您的 onCreate 方法中,使用视图的 id 名称来设置任何侦听器:-
binding.textView.setOnLongClickListener(this::onLongClick);
然后只需创建一个具有相同名称的布尔方法,即 onLongClick 如下所示:-
private boolean onLongClick(View l)
Toast.makeText(this, "Description", Toast.LENGTH_SHORT).show();
return true;
就是这样!!
注意:您还可以通过在 onCreate 方法中为活动变量设置上下文来为布局中的任何视图设置任何方法:-
binding.setActivity(this);
然后,在布局中定义并传递方法名称和视图,以便在 Activity 文件中使用它。就像我为我的Textview 使用了一个变量名为“activity”的方法changeDescText(v)。 这是我在 Activity 文件中的方法:-
public void changeDescText(View view)
binding.setTempDesc("Description Changed");
【讨论】:
不要在数据绑定中保存活动引用,否则会导致内存泄漏。 @TheLibrarian 你有这方面的资料吗?以上是关于使用 DataBinding 库绑定事件的主要内容,如果未能解决你的问题,请参考以下文章
仅对具有 DataBinding 事件的对象提供数据绑定表达式支持。System.Web.UI.WebControls.HyperLinkField 没
Android dataBinding 之 配合使用BaseAdapter适配器
一起Talk Android吧(第三百八十五回:数据绑定-DataBinding总结)