Jetpack学习-6-Viewbinding使用及简单分析

Jetpack可以帮助开发者减少样板代码,而findviewbyId正是需要减少的样板代码,于是就有了ViewBinding。一开始我细看Jetpack的各个组件我是懵的,里面没有ViewBinding,这不好把它归纳到Jetpack系列中,后面通过底层源码分析,它是Gradle将DataBinding中识图绑定功能单独抽离出来的一个子集,所以也算是Jetpack中的一员。

简单分析

下面是ViewBinding的简单使用,当前使用的Android Gradle Plugin版本为4.1.0及4.2.0

0,当Android Gradle Plugin 版本4.1.0时,项目中有个androidx.databinding:viewbinding:4.1.0@aar的依赖,当AndroidGradlePluginVersion切换到4.2.0时,viewbinding依赖变为androidx.databinding:viewbinding:4.2.0@aar,果然,和databinding有关系,和AndroidGradlePlugin版本也有联系,依赖中有ViewBinding类。

ViewBinding源码如下

package androidx.viewbinding;

import android.view.View;
import androidx.annotation.NonNull;

/** A type which binds the views in a layout XML to fields. */
public interface ViewBinding {

    @NonNull
    View getRoot();
}

Viewbinding在Activity上的使用及分析

1,在项目中的gradle中

android{
	 //android4.0之前
     viewBinding{
     	enabled=true
    }

    
     //androidstudio4.0以上
	 buildFeatures {
       	viewBinding true
   	}
}

2, 系统会对每一个布局文件即时默认生成一个Binding类

如果不需要对布局文件进行绑定,可在布局根节点中添加下述属性:

tools:viewBindingIgnore="true" >

 3,生成文件的路径在build\generated\data_binding_base_class_source_out\debug\out\com\sun\viewbinding\databinding上,查看布局及生成的文件,并在activity中添加布局

1)xml布局 activity_main5.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/bt_showframe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="显示" />

    <TextView
        android:id="@+id/tv_myName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World,I am module 5!" />

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>






2)生成的文件 ActivityMain5Binding.java

package com.sun.viewbinding.databinding;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewbinding.ViewBinding;
import com.sun.viewbinding.R;
import java.lang.NullPointerException;
import java.lang.Override;
import java.lang.String;

public final class ActivityMain5Binding implements ViewBinding {  //实现了ViewBinding中的getRoot()方法
  @NonNull
  private final LinearLayout rootView;							  //布局中的根布局,是private修饰,保证安全

  @NonNull
  public final Button btShowframe;								//全是public修饰,保证快捷访问

  @NonNull
  public final FrameLayout frame;								//全是public修饰,保证快捷访问

  @NonNull
  public final TextView tvMyName;								//全是public修饰,保证快捷访问



  @NonNull
  public static ActivityMain5Binding inflate(@NonNull LayoutInflater inflater) {//传入解析器,进行进行布局解析
    return inflate(inflater, null, false);
  }

  @NonNull
  public static ActivityMain5Binding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup parent, boolean attachToParent) {
    View root = inflater.inflate(R.layout.activity_main5, parent, false);			//ActivityMain5Binding.java类解析activity_main5.xml
    if (attachToParent) {
      parent.addView(root);
    }
    return bind(root);
  }

  @NonNull
  public static ActivityMain5Binding bind(@NonNull View rootView) {
    // The body of this method is generated in a way you would not otherwise write.
    // This is done to optimize the compiled bytecode for size and performance.
    int id;
    missingId: {
      id = R.id.bt_showframe;
      Button btShowframe = rootView.findViewById(id);								//终究也还是通过findviewbyId进行id与view的关联
      if (btShowframe == null) {
        break missingId;
      }

      id = R.id.frame;
      FrameLayout frame = rootView.findViewById(id);
      if (frame == null) {
        break missingId;
      }

      id = R.id.tv_myName;
      TextView tvMyName = rootView.findViewById(id);
      if (tvMyName == null) {
        break missingId;
      }

      return new ActivityMain5Binding((LinearLayout) rootView, btShowframe, frame, tvMyName);
    }
    String missingId = rootView.getResources().getResourceName(id);
    throw new NullPointerException("Missing required view with ID: ".concat(missingId));
  }

  private ActivityMain5Binding(@NonNull LinearLayout rootView, @NonNull Button btShowframe,
      @NonNull FrameLayout frame, @NonNull TextView tvMyName) {
    this.rootView = rootView;
    this.btShowframe = btShowframe;
    this.frame = frame;
    this.tvMyName = tvMyName;
  }

  @Override
  @NonNull
  public LinearLayout getRoot() {								//实现自ViewBinding
    return rootView;
  }
}







3,MainActivity.java 使用绑定类

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMain5Binding binding = ActivityMain5Binding.inflate(getLayoutInflater());//给绑定类传入解析器
        setContentView(binding.getRoot());//activity添加布局
        binding.tvMyName.setText("hello,My name is lilei");//更改布局
    }
}

这样,viewbinding在activity上就使用好了。

ViewBinding在Fragment中的使用

import com.sun.viewbinding.databinding.FragmentHelloBinding;

public class HelloFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        FragmentHelloBinding binding = FragmentHelloBinding.inflate(inflater, container, false);
        binding.tvFragmentHello.setText("hello,I am hanmeimei in Fragment");
        return binding.getRoot();
    }
}

ViewBinding在Dialog中的使用

public void showDialog() {
        Dialog dialog = new Dialog(this);
        DialogHelloBinding binding = DialogHelloBinding.inflate(dialog.getLayoutInflater());
        dialog.setContentView(binding.getRoot());
        binding.tvDialogHello.setText("你好,我是dialog Poly");
        dialog.show();
    }

ViewBinding在RecycleView+Adapter中的使用

import com.sun.viewbinding.databinding.ItemStudentBinding;

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHold> {


    private ArrayList<Student> beans;

    public StudentAdapter(ArrayList<Student> beans) {
        this.beans = beans;
    }

    @NonNull
    @Override
    public StudentViewHold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       ItemStudentBinding binding= ItemStudentBinding.inflate(LayoutInflater.from(parent.getContext()));

        return new StudentViewHold(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull StudentViewHold holder, int position) {
        Student bean = beans.get(position);
        holder.tv_age.setText("年龄=" + bean.age);
        holder.tv_name.setText("名字=" + bean.name);
    }

    @Override
    public int getItemCount() {
        return beans.size();
    }

    class StudentViewHold extends RecyclerView.ViewHolder{
        TextView tv_name;
        TextView tv_age;

        public StudentViewHold(ItemStudentBinding binding) {
            super(binding.getRoot());
            tv_name=binding.tvName;
            tv_age=binding.tvAge;
        }
    }
}

小结

总得来说,viewbinding是相当简单并且实用的,相比传统的直接findviewbyid省去了类型转换,也保证了控件的空安全,传入解析器就能自动得到view,也能得到根view下的子view,可以有效避免张冠李戴,这一切都是因为Android Gradle Plugin自动对全部的布局文件进行了封装绑定,在java层只需对绑定类进行直接操作即可,Android Gradle Plugin如何生成绑定类后续再深入分析吧。

Android-Jetpack代码位置:github

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_Sun_01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值