AndroidStudio ViewBinding详解

前言

  在Android开发,代码里获取View一般是使用findViewById()获取目标布局文件里的指定View。但是这样使用会有大量代码重复工作并且有空指针危险。为了减少重复工作有很多大神都八仙过海各显神通,但是这些神通多多少少都有缺点。

  • 大名鼎鼎的黄油刀bufferknife,缺点增加了编译速度(因为原理是它需要生成一份对应查找View的代码),并且需要时刻更新最新版本否则AndroidStudio更新后可能会出现无法编译的问题。(另外bufferknife与ViewBinding是冲突的)
  • DataBinding,缺点更明显,需要更多的xml编写工作量,并且一不小心会延伸到一些邪恶的用法,那就是在xml写逻辑判断,甚至在xml增加一些业务功能。这对代码维护是恐怖的,因为xml逻辑的可读性可比纯Java代码差多了。并且如果混乱到2头都写逻辑判断,维护起来十分痛苦。
  • AndroidStudio的插件功能自动生成代码,比如LayoutCreator,减少了工作量但是并没有减少代码的冗余,代码看起来一样是不简洁的。

google在AndroidStudio 3.6 版本后推出了ViewBinding,一方面可以让代码更加简洁并且提高编译速度防止空指针。另一方面AndroidStudio是支持ViewBinding进行关联互动的,所以让你在Java代码与xml之间的跳转更方便。

前提条件

  AndroidStudio 需要更新到3.6版本以上。

在build.gradle文件里增加下面的代码,开启viewBinding

android {
    
    //略...

    viewBinding{
        enabled = true;
    }
}

各处简单的使用Demo

首先你需要知道一个关键点,在启用ViewBinding后。每一个layout文件都会自动生成一份Java类。它会自动根据下划线进行驼峰命名。比如一个叫 activity_mian_demo.xml 的布局文件,它对应自动生成的类叫ActivityMianDemoBinding。这就意味着我们可以在任何需要导入布局的地方都使用ViewBinding。

Activity里:

public class MainActivity extends AppCompatActivity {
    private ActivityMianDemoBinding mBinding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityMianDemoBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());
        mBinding.btn1.setText("这是按键1");
        mBinding.btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });
    }
}

Fragment里:

public class FragmentDemo extends Fragment {
    private FragmentDemoBinding mBinding;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mBinding = FragmentDemoBinding.inflate(getLayoutInflater());
        return mBinding.getRoot();
    }
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mBinding.textView.setText("textView");
    }
}

在Dialog里:

public class DemoDialog extends Dialog {
    private DialogDemoBinding mBinding;
    public DemoDialog(@NonNull Context context) {
        super(context);
        mBinding = DialogDemoBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());
        mBinding.textView.setText("hello");
    }
}

Adapter里:

public class DemoAdapter extends RecyclerView.Adapter<DemoAdapter.ViewHolder> {
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewHolder(ItemDemoBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.binding.textView2.setText("demo");

    }
    @Override
    public int getItemCount() {
        return 0;
    }
    public static class ViewHolder extends RecyclerView.ViewHolder {
        ItemDemoBinding binding;
        public ViewHolder(@NonNull ItemDemoBinding itemDemoBinding) {
            super(itemDemoBinding.getRoot());
            this.binding = itemDemoBinding;
        }
    }
}

xml属性include

在之前其他人的博客里有说ViewBinding还不支持include属性。但是在这篇博客发布的时间,最新版本AndroidStudio4.0的已经支持使用了include属性。

使用include的布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <include
        android:id="@+id/title"
        layout="@layout/title_layout"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <Button
        android:id="@+id/btn_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="A1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity里:

public class MainActivity extends AppCompatActivity {
    private ActivityMianDemoBinding mBinding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityMianDemoBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());
        mBinding.title.titleContent.setText("内容");
        mBinding.title.titleContent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this, "点击", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

假如你有需求要分离include的布局,单独使用这个include布局的类,可以参考如下实现:

public class MainActivity extends AppCompatActivity {
    private ActivityMianDemoBinding mBinding;
    private TitleLayoutBinding mTitleLayoutBinding;
    @Override

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityMianDemoBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());
        mTitleLayoutBinding = TitleLayoutBinding.bind(mBinding.getRoot());
        mTitleLayoutBinding.titleContent.setText("内容11");
    }
}

End

原文地址:https://www.cnblogs.com/guanxinjing/p/13234469.html