刚接触的databinding ,这个东西的好处就是省代码,不过在我看来是脱离菜鸟的第一步:不用再findViweById()
他的用法摸索了很久,还是在老师傅的指导下走了几遍才会皮毛。
public class User{
public String firstname;
public String lastname;
//构造传递参数
public User(String firstname,String lastname){
this.firstname= firstname;
this.lastname = lastname;
}
//set get方法
}
//在其他地方调用这个类,比如在另一个activity中需要使用到String类型的参数的时候,就可以调用这个类的方法来给布局传递参数
//当然,这个activity或者别的什么界面,是要被绑定的。
1 在app的builde.gradle文件中添加一句话在android{}中
dataBinding {
enabled true
}
// 2 接下来创建activity
我们平时在创建activity的时候,需要OnCreate()方法,这里一样需要这个方法,但是在加载布局的时候不再是直接setContentView(R.layout.activity_xxx);
而是通过一个工具类,不是我们创建的工具:
DataBindingUtil
通过这个工具加载一个布局,就可以返回我们创建的经过绑定的类的对象(面向对象);
ActivityDynamicBinding dynamicBinding = DataBindingUtil.setContentView(this, R.layout.activity_dynamic);
这个类命名的方法是Activity+ XXX(名字) + Binding ,
如果是fragment, 名字就是Fragment + XXX(名字) + Binding;
//3 当然,之前的都是挺简单的,这么有用的东西怎么能不特殊呢?
开始建造布局:
以layout开头,在中,声明类,或者变量,
这样就可以在布局中使用user
就比如在上布局中
dynamicActivity
代表的就是type中的
DynamicActivity
这是用就可以在代码中写这么一句:
ActivityDynamicBinding dynamicBinding = DataBindingUtil.setContentView(this, R.layout.activity_dynamic);
就不用再findViewByid(),一切都可以直接从binding赋值。
得到这个对象以后,在布局中设置两个TextView,一个让他显示firstname,另一个显示lastname,
在onCreate()中得到绑定的对象以后,
User user = new User("first","last");
binding.setUser(user);
就会看到,我们虽然没有给TextView 赋值,但是我们的text却得到了答案,只因给user赋值了,他们就自己得到了值;
再举个栗子:
上面的布局中,有这么一段
omi:centerText="@string/dynamic"
这个方法,系统如果在运行的时候走的是TopNavigationBar中的setConterText方法;
有证据:
也就是说:如果你的方法中没有setCenterText()方法,这个dataBinding就不能运行,即便是错了一个单词都不行!
是的,等号左边的属性中,对应的是一个首字母大些的set方法: rightClick="XXX" 指的就是 setRightClick(),而这个方法存在
TopNavigationBar 之中!
等号的右边,对应的就是一个返回值: 比如左边要什么参数或者什么效果,右边的参数就必须返回左边的需要。
omi:leftClick="@{@string/top_left_click}"
等号右边返回的是一个字符串,就说明setLeftClick()方法中需要一个字符串。
//接下来就属于比较难点的东西了。
setLeftClick()方法在TopNavigationBar中,
public void setLeftClick(String methodName) {
if (methodName != null) {
navigationBarBinding.leftRL.setOnClickListener(new DeclaredOnClickListener(navigationBarBinding.leftRL, methodName));
}
}
*/
public class DeclaredOnClickListener implements View.OnClickListener {
private final View mHostView;
private final String mMethodName;
private Method mResolvedMethod;
private Context mResolvedContext;
public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
mHostView = hostView;
mMethodName = methodName;
}
@Override
public void onClick(@NonNull View v) {
if (mResolvedMethod == null) {
resolveMethod(mHostView.getContext(), mMethodName);
}
try {
mResolvedMethod.invoke(mResolvedContext, v);
} catch (IllegalAccessException e) {
throw new IllegalStateException(
"Could not execute non-public method for android:onClick", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException(
"Could not execute method for android:onClick", e);
}
}
@NonNull
private void resolveMethod(@Nullable Context context, @NonNull String name) {
while (context != null) {
try {
if (!context.isRestricted()) {
final Method method = context.getClass().getMethod(mMethodName, View.class);
if (method != null) {
mResolvedMethod = method;
mResolvedContext = context;
return;
}
}
} catch (NoSuchMethodException e) {
// Failed to find method, keep searching up the hierarchy.
}
if (context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
} else {
// Can't search up the hierarchy, null out and fail.
context = null;
}
}
final int id = mHostView.getId();
final String idText = id == View.NO_ID ? "" : " with id '"
+ mHostView.getContext().getResources().getResourceEntryName(id) + "'";
throw new IllegalStateException("Could not find method " + mMethodName
+ "(View) in a parent or ancestor Context for android:onClick "
+ "attribute defined on view " + mHostView.getClass() + idText);
}
}
这个方法告诉我:
绑定过的imageView设置了一个监听,传递了监听的控件对象,和String methodName;
进入自定义监听:
1 通过这个控件.getContext()得到context的对象,然后在判断这个类是否受限,不受限的话,就在调用了这个控件的类中找到名字为Methodname的方法,
就是传递进来的String类型数据的字符串,找到这个方法之后就可以调用这个方法,如果没有找到,抱歉我并没有做什么处理。因为我在传递时就保证肯定会找到,不然就自杀。
结果:在调用了这个控件的类中创建一个set方法,然后在属性中输入。具体的请联系我,刚学不懂的太多。