Android开发提升效率之DataBinding——进阶开发

DataBingding

  1. Android开发提升效率之DataBinding——基本使用
  2. Android开发提升效率之DataBinding——进阶开发
  3. Android开发提升效率之DataBinding——双向绑定

博客创建时间:2021.04.12
博客更新时间:2021.04.13

以Android studio build=4.1.3,gradle=6.5,SdkVersion 30来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已


前言

在上一篇博文《Android开发提升效率之DataBinding——基本使用》中,已经对DataBinding有了基本的掌握和使用能力,本篇博文主要对另一些进阶开发做详细的描述和讲解。


RecyclerView中的使用

public class ListSubjectAdapter extends RecyclerView.Adapter<ListSubjectAdapter.ViewHolder> {
    private List<TableSubject> list;
    MyOnItemClickListener myOnItemClickListener;
    
    public void setMyOnItemClickListener(@NonNull MyOnItemClickListener myOnItemClickListener) {
        this.myOnItemClickListener = myOnItemClickListener;
    }

    public ListSubjectAdapter() {
    }

    public void setDatas(@NonNull List<TableSubject> data) {
        this.list = data;
        notifyDataSetChanged();
    }

    @NonNull
    public TableSubject getItem(int position) {
        return list.get(position);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, int viewType) {
        ItemListSubjectBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_list_subject, parent, false);
        return new ViewHolder(binding);
    }


    public void removeList(int position) {
        if (list != null) {
            //删除数据源,移除集合中当前下标的数据
            list.remove(position);
            //刷新被删除的地方
            notifyItemRemoved(position);
            //刷新被删除数据,以及其后面的数据
            notifyItemRangeChanged(position, getItemCount());
        }
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, @SuppressLint("RecyclerView") final int position) {
        holder.getBinding().setBean(list.get(position));
        holder.getBinding().getRoot().setOnClickListener(v -> {
            if (myOnItemClickListener != null) {
                myOnItemClickListener.myOnItemClick(position, list.get(position).getSubjectId());
            }
        });

        holder.getBinding().getRoot().setOnLongClickListener(v -> {
            return false;
        });
        holder.binding.executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return list == null ? 0 : list.size();
    }

    private void removeItemByPosition(int position) {
        list.remove(position);
        notifyDataSetChanged();
    }

    public long getId() {
        return getItem(currentPosition).getSubjectId();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final ItemListSubjectBinding binding;

        ViewHolder(ItemListSubjectBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }

        ItemListSubjectBinding getBinding() {
            return binding;
        }
    }

}

RecyclerView中的闪烁问题

@Override
public void onBindViewHolder(@NonNull UserAdapterHolder holder, int position) {
        holder.getBinding().setClassName(beans.get(position));
        holder.getBinding().setAdapter(this);
        holder.getBinding().setPosition(position);
        holder.binding.executePendingBindings();
}

holder.binding.executePendingBindings()这个不加上可能会控件显示异常现象。


BindingAdapter注解使用

对于图片的加载,我们可以使用BindingAdapter注解来解决,这样就不用每次都进行ImageView的图片设置操作

public class ImageHelper {
    /**
     * 1.加载图片,无需手动调用此方法
     * 2.使用@BindingAdapter注解设置自定义属性的名称,imageUrl就是属性的名称,
     * 当ImageView中使用imageUrl属性时,会自动调用loadImage方法,
     *
     * @param imageView ImageView
     * @param url       图片地址
     */
    @BindingAdapter({"imageUrl"})
    public static void loadImage(ImageView imageView, String url) {
        Glide.with(imageView.getContext()).load(url)
                .placeholder(R.mipmap.fruit)
                .error(R.mipmap.fruit)
                .into(imageView);
    }
}

loadImage()一定需要是static修饰

ImageView中配置imageUrl。当图片未加载出来时会有一张图片,如果加载错误则会有另一张图片。

// 具体的使用形式
   <!-- 当imageUrl属性存在时,会自动调用ImageHelper的loadImage方法,
   参数imageView为当前使用imageUrl属性的ImageView,参数url为图片地址 -->
        <ImageView
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:scaleType="centerCrop"
            app:imageUrl="@{user.picUrl}" />

其他Tip

1. include中的数据传递
如果在Activity的xml布局使用了include标签,此时想将Activity xml中设置的如click传递给layout,可以进行如下操作。

 <data>
       <variable name="user" type="com.example.User"/>
 </data>

 <include 
    layout="@layout/contact"
    app:user="@{user}"/>
// 可以是app:user或者bind:user,其实都一样的可以

2. Data binding不支持直接包含merge 节点
//举个例子, 以下的代码不能正常运行 :

  <merge>
       <include layout="@layout/contact"
         app:user="@{user}"/>
   </merge>

3. 事件处理使用方式

方式一:  
android:onClick="@{clickListener}"

方式二:
//使用该种方法时末尾是没有  "()"的,要特别注意
android:onClick="@{handler::onClickFriend}"/>
<!-- 注意:函数名和监听器对象必须对应 -->
<!-- 函数调用也可以使用 `.` , 如handler.onClickFriend , 不过已弃用 -->
    
方式三
android:onCheckedChanged="@{(view,cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
或
android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />

方式二相对于方式一,它的优势在于表达式会在编译时处理,如果方法不存在或者方法签名不对,编译将会报错。


表达式支持

DataDinding中和Java一样支持多种运算符

	1. 常规三目运算
	android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"

	2.还有如下 格式  ??符号相当于三目运算的简写
	android:text="@{user.displayName ?? user.lastName}"
	android:text="@{user.displayName != null ? user.displayName : user.lastName}"

	3.静态方法的使用
	<TextView   android:text="@{MyStringUtils.capitalize(user.firstName)}" />
	
	4. 固定内容和变量表达式
	android:text='@{"iname:" +user.name}'
	有时会报错,此时使用如下样式进行解决
	android:text='@{@String/iname +user.name}'

支持的运算符支持的运算符支持的运算符
数学计算 + - / * %字符串连接 +逻辑 && “11”
二进制 & 和^一元 + - ! ~位移 >> >>> <<
比较 == > < >= <=instanceof组 ()
字面量 - 字符,字符串,数字, null类型转换函数调用
字段存取数组存取 []三元运算符 ?:
不支持的运算符不支持的运算符不支持的运算符
thissupernew
显式泛型调用

转义符

在xml布局文件中使用<、>、&、%等符号时会出现错误,此时我们需要将这些特殊符号进行转义,才能正常使用。

    <data>
         
        <!-- 这种方式是错误的-->
        <variable
            name="list"
            type="java.util.List<String>" />
            
         <!--此方式正确-->
        <variable
            name="list"
            type="java.util.List&lt;String&gt;" />
    </data>
显示结果描述转义字符十进制
空格&nbsp;&#160;
<小于号&lt;&#60;
>大于号&gt;&#62;
&与号&amp;&#38;
"引号&quot;&#34;
撇号&apos;&#39;
*乘号&times;&#215;
%除号&divide;&#247;

总结

本篇博客主要对DataBinding框架的使用中,一些进阶知识点进行总结和归纳。

本测试Demo源码
https://gitee.com/luofaxin/DataBindingAnalysis.git
https://github.com/l424533553/DataBindingAnalysis.git


相关链接

  1. Android开发提升效率之DataBinding——基本使用
  2. Android开发提升效率之DataBinding——进阶开发
  3. Android开发提升效率之DataBinding——双向绑定

扩展链接:

  1. 最通俗易懂的教你使用RxJava3(一)

扩展训练:

  1. BindingAdapter注解使用
  2. RecyclerView控件的使用
  3. 转义符、运算符的使用

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值