Android Zone

Android viewBinding使用简介

2020-09-26  本文已影响0人  翻译不了的声响

viewBinding(视图绑定)通过视图绑定功能,可以更轻松地编写可与视图交互的代码。在模块配置文件中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。

1. 视图绑定对比

与使用 findViewById 相比,视图绑定具有一些很显著的优点:

这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。

2. 视图绑定配置

视图绑定在需要在 Android Studio 3.6 及更高版本中才能使用。

视图绑定功能可按模块启用,在需要的模块build.gradle文件中添加viewBinding元素启用视图绑定:

android {       
  ...        
    viewBinding {
        enabled = true      
    }  
}    

如果在生成绑定类时忽略某个布局文件,可以在相应布局文件的根视图中添加tools:viewBindingIgnore="true"属性即可:

 <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:viewBindingIgnore="true">
     ...
 </RelativeLayout>
3. 视图绑定用法

为某个模块启用视图绑定功能后,系统会为该模块中包含的每个 XML 布局文件生成一个绑定类。每个绑定类均包含对根视图以及具有 ID 的所有视图的引用。系统会在项目模块下的build/generated/data_binding_base_class_sources_out/debug/out/包名/databinding目录下,将 XML 文件的名称转换为驼峰式大小写方式生成绑定类的名称,并在末尾添加“Binding”

生成绑定类路径图

例如一个布局文件的名称为activity_main.xml

<LinearLayout 
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical" >
      <TextView android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

      <Button android:id="@+id/btn_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/button_bg" />
    </LinearLayout>

所生成的绑定类的名称就为:ActivityMainBinding,生成类中包含:布局中 id 的View、为相应布局文件的根视图提供直接引用的getRoot()方法、创建绑定类的实例提供引用的静态inflate()方法。

生成绑定类源码图
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
    }
    

绑定类配置完,就可以使用该绑定类的实例来引用xml布局中的视图:

    binding.tvName.setText("Activity");
    binding.btnButton.setOnClickListener(new View.OnClickListener() {
        finish();
    });    
    private ActivityMainBinding binding;

    @Override
    public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = ActivityMainBinding.inflate(inflater, container, false);
        View view = binding.getRoot();
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
    

绑定类配置完,就可以使用该绑定类的实例来引用xml布局中的视图:

    binding.tvName.setText("Fragment");
    binding.btnButton.setOnClickListener(new View.OnClickListener() {
        finish();
    });    
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
   ...    

  @NonNull
  @Override
  public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
      ItemTestBinding binding = ItemTestBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
      return new ViewHolder(binding);
  }

  @Override
  public void onBindViewHolder(@NonNull final MyAdapter.ViewHolder holder, final int position) {
      holder.binding.tvTitle.setText("测试内容");
  }

  public class ViewHolder extends RecyclerView.ViewHolder{    
     ItemTestBinding binding;
     public ViewHolder(ItemTestBinding itemBinding) {
        super(itemBinding.getRoot());
        binding = itemBinding;
     }
  }

}

2)在继承BaseAdapter的类中使用
如果在继承 BaseAdapter类中使用绑定类的实例,需要在 BaseAdapter中的getView()方法中执行以下步骤:
(1) 创建一个ViewHolder缓存类,声明绑定类对象;
(2) 在getView()方法中,没有缓存时,调用生成的绑定类中包含的静态inflate()方法创建该绑定类的实例并传入创建的ViewHolder类中,通过调用getRoot()方法获取根视图,然后调用convertView的setTag()方法,传入ViewHolder对象,建立起了convertView与ViewHolder之间的关系;如果有缓存时,调用convertView的getTag()取得关联的对象,将返回结果赋给ViewHolder引用;
(3) 通过创建的ViewHolder类中的绑定类对象获取布局中的视图,并赋值展示。

public class MyAdapter extends BaseAdapter {
    ...

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            ItemTestBinding binding = ItemTestBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
            holder = new ViewHolder(binding);
            convertView = binding.getRoot();
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        
        holder.binding.tvTitle.setText("测试内容");
        return convertView;
    }

    class ViewHolder {
        public ItemTestBinding binding;
        public ViewHolder(ItemTestBinding itemBinding) {
            binding = itemBinding;
        }
    }

}

上一篇 下一篇

猜你喜欢

热点阅读