---error: duplicate attribute.
估计很多人遇到后都不知道怎么办,但一直提示layout文件有问题,所以就尝试将跟布局的width和height属性去掉,然后就没有这个问题了
---有ViewPager的界面必须为ViewPager设置一个id
在没有使用DataBinding的时候,通常都会为ViewPager设置一个id.有一次在使用的时候结合DataBinding,所以就没有设置id,所以就抛出必须设置id异常.
---找不到BR类
在使用DataBinding的时候,偶尔需要用到BR类,然而有时要用的时候总会找不到.
这个时候各种clean,rebuild都没用,检查layout文件的代码也没发现问题.在生成的DataBinding类里面把BR类复制出来编译不会报错,运行的时候发现报错了.所以最后想到了用反射根治这个问题,虽然这种方式并不方便,但也算是解决了这个问题.
public static int getBrField(String fieldName){
int fieldId = 0;
try{
Class brClass = Class.forName(MyApplication.getInstance().getPackageName() + ".BR");
Object brObject = brClass.newInstance();
fieldId = (int)(brClass.getField(fieldName).get(brObject));
}catch(Exception e){
e.printStackTrace();
}
return fieldId;
}
注意: 使用了反射之后有开启代码混淆的话必须在混淆规则忽略混淆
-keep class 你的包名.BR { *;}
---没办法使用&&符号的问题
相信有些人可能遇到这个问题,其实不知没办法在@{}里面使用 & 符号,在双引号里面也没办法使用.我一开始也没反应过来,后来
android:text="&" 这里试了一下才想起来这里要用转义,遇到这个问题的人估计很少在layout文件里面写 & 符号,所以一时半会没反应过来.还有,<> 这2个符合也需要使用转义.
常用转义表
2025年更新,最近接手了一个项目,该项目里面用了DataBinding。看到layout里面大量的逻辑代码血压真的上来的,代码可读性极差。
一开始学习DataBinding时,我也总在layout里面写逻辑代码。后来发现,这种方式可读性极差,特别是,涉及到的变量越多,可读性越差。更好的做法是在ViewModel声明一个新的变量来处理业务。
以下是针对该问题,我编写的解决方式,有1个、2个、3个和4个LiveData对象数据类型的转换。
1个变量时:
public class TestViewModel {
public MutableLiveData<Boolean> isShow = new MutableLiveData<>();
// 单个变量转换时,使用Transformations.map
public LiveData<Integer> showValue = Transformations.map(isShow, it -> it? View.VISIBLE: View.GONE);
// 也可以编写通用方法showToValue,以后存在同样需求时直接调用方法即可
public LiveData<Integer> showValue2 = Transformations.map(isShow, this::showToValue);
public int showToValue(boolean isShow) {
return isShow? View.VISIBLE: View.GONE;
}
}
多个变量时,创建工具类来解决:
LiveDataCombineUtil
public class LiveDataCombineUtil {
public static <R, P1, P2> LiveData<R> combineLiveData(LiveData<P1> p1, LiveData<P2> p2, Function2<R, P1, P2> action) {
MediatorLiveData<R> liveData = new MediatorLiveData<>();
liveData.addSource(p1, it -> {
liveData.setValue(action.invoke(it, p2.getValue()));
});
liveData.addSource(p2, it -> {
liveData.setValue(action.invoke(p1.getValue(), it));
});
return liveData;
}
public static <R, P1, P2, P3> LiveData<R> combineLiveData(LiveData<P1> p1, LiveData<P2> p2, LiveData<P3> p3, Function3<R, P1, P2, P3> action) {
MediatorLiveData<R> liveData = new MediatorLiveData<>();
liveData.addSource(p1, it -> {
liveData.setValue(action.invoke(it, p2.getValue(), p3.getValue()));
});
liveData.addSource(p2, it -> {
liveData.setValue(action.invoke(p1.getValue(), it, p3.getValue()));
});
liveData.addSource(p3, it -> {
liveData.setValue(action.invoke(p1.getValue(), p2.getValue(), it));
});
return liveData;
}
public static <R, P1, P2, P3, P4> LiveData<R> combineLiveData(LiveData<P1> p1, LiveData<P2> p2, LiveData<P3> p3,LiveData<P4> p4, Function4<R, P1, P2, P3, P4> action) {
MediatorLiveData<R> liveData = new MediatorLiveData<>();
liveData.addSource(p1, it -> {
liveData.setValue(action.invoke(it, p2.getValue(), p3.getValue(), p4.getValue()));
});
liveData.addSource(p2, it -> {
liveData.setValue(action.invoke(p1.getValue(), it, p3.getValue(), p4.getValue()));
});
liveData.addSource(p3, it -> {
liveData.setValue(action.invoke(p1.getValue(), p2.getValue(), it, p4.getValue()));
});
liveData.addSource(p4, it -> {
liveData.setValue(action.invoke(p1.getValue(), p2.getValue(), p3.getValue(), it));
});
return liveData;
}
}
下面是几个Function,如果开发语言用的是kotlin,也可以直接替换成kotlin的Function类。
public interface Function2<R, P1, P2> {
R invoke(P1 p1, P2 p2);
}
public interface Function3<R, P1, P2, P3> {
R invoke(P1 p1, P2 p2, P3 p3);
}
public interface Function4<R, P1, P2, P3, P4> {
R invoke(P1 p1, P2 p2, P3 p3, P4 p4);
}
调用LiveDataCombineUtil对应的方法,就能联合多个LiveData。实际开发中,用得比较多的是2个和3个LiveData,所以就没有编写更长参数列表。
如果开发语言的kotlin,还能直接为LiveData编写扩展方法,让代码写起来更方便,这里我就不展开了。