Android 使用ViewBinding视图绑定

柯波峻
2023-12-01

目前,谷歌在 Android Studio 3.6 Canary 11 及更高版本中加入了新的视图绑定方式ViewBinding。
注意:要使用ViewBinding功能,AndroidStudio至少要升级到3.6。

使用方法

在要使用ViewBinding的 module 的build.gradle文件中开启ViewBinding

android {
    ……………
    viewBinding {
        enabled = true
    }
    ……………
}

如果在使用的过程中不想为某个布局文件生成binding类,则可以使用如下属性添加到布局的根视图中:

<androidx.constraintlayout.widget.ConstraintLayout
  …………
      tools:viewBindingIgnore="true" >
  …………
</androidx.constraintlayout.widget.ConstraintLayout>

在gradle文件中开启ViewBinding功能后,编译器就会为此模块下的每个布局文件都产生一个对应的绑定类。
这个绑定类是我们的布局名称去掉下划线使用驼峰的形式结尾接Binding;
例如:
activity_gender_guide.xml
就是:
ActivityGenderGuideBinding

使用viewbinding后,不需要再findViewById找控件,
直接通过binding.控件Id名称就可以,控件id名称也是去掉下滑线使用驼峰的形式。
viewbinding的inflate有两种方法,根据直接所需选择
1:inflate(getLayoutInflater());
2:inflate(inflater, container, false);

在Activity里使用

public class GenderGuideActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //之前的写法
        setContentView(R.layout.activity_gender_guide);
        TextView guide_title = (TextView) findViewById(R.id.guide_title);
        guide_title.setText("标题");
        
        //使用viewbinding的写法
        ActivityGenderGuideBinding binding = ActivityGenderGuideBinding.inflate(getLayoutInflater());
		setContentView(binding.getRoot());
		binding.guideTitle.setText("标题");
     }

在Fragment里使用

public class ReadingHistoryFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    	//以前的写法
    	View view = inflater.inflate(R.layout.list_with_empty_view, null);
    	TextView empty_text = (TextView) view.findViewById(R.id.empty_text);
    	empty_text.setText("标题");
    	return view;
    	//使用viewbinding的写法
        ListWithEmptyViewBinding binding = ListWithEmptyViewBinding.inflate(inflater, container, false);
        binding.emptyText.setText("标题");
        return binding.getRoot();
    }

}

在BaseAdapter里使用

以前的写法

public class ListAdapter extends BaseAdapter {
    private Activity activity;
    private List<String> list;

    public ListAdapter(Activity activity, List<String> list) {
        this.activity = activity;
        this.list = list;
    }

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

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    class ViewHolder {
        ImageView iv_cover;
        TextView tv_bookname;
        TextView tv_author;
        TextView tv_url_or_chapter;
        TextView tv_archive_date;
        ImageView iv_popup_hint;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(activity).inflate(R.layout.archive_list_item, null);
            holder = new ViewHolder();
            holder.iv_cover = (ImageView) convertView.findViewById(R.id.iv_cover);
            holder.tv_bookname = (TextView) convertView.findViewById(R.id.tv_bookname);
            holder.tv_author = (TextView) convertView.findViewById(R.id.tv_author);
            holder.tv_url_or_chapter = (TextView) convertView.findViewById(R.id.tv_url_or_chapter);
            holder.tv_archive_date = (TextView) convertView.findViewById(R.id.tv_archive_date);
            holder.iv_popup_hint = (ImageView) convertView.findViewById(R.id.iv_popup_hint);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        return convertView;
    }
    }

使用viewbinding的写法

public class ListAdapter extends BaseAdapter {
    private Activity activity;
    private List<String> list;

    public ListAdapter(Activity activity, List<String> list) {
        this.activity = activity;
        this.list = list;
    }

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

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ArchiveListItemBinding binding; 
        if (convertView == null) {
            binding = ArchiveListItemBinding.inflate(activity.getLayoutInflater(), null, false);
            convertView = binding.getRoot();
            convertView.setTag(binding);
        } else {
            binding = (ArchiveListItemBinding) convertView.getTag();
        }
        binding.tvBookname.setText("标题");
        return convertView;
    }
    }

在RecyclerView结合Adapter使用

public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {

    private List<String> mList;

    public MainAdapter(List<String> list) {
        mList = list;
    }

    @NonNull
    @Override
    public MainAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //之前的写法
        //View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_comment_item, parent, false);
        //ViewHolder holder = new ViewHolder(view);

        //使用ViewBinding的写法
        LayoutCommentItemBinding commentItemBinding = LayoutCommentItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
        ViewHolder holder = new ViewHolder(commentBinding);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull MainAdapter.ViewHolder holder, int position) {
        holder.mTextView.setText("标题");
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView mTextView;
        //之前的写法
        //public ViewHolder(@NonNull View itemView) {
        //    super(itemView);
        //    mTextView = itemView.findViewById(R.id.tv_name);
        //}

        //使用ViewBinding的写法
        ViewHolder(@NonNull LayoutCommentItemBinding commentItemBinding) {
            super(commentItemBinding.getRoot());
            mTextView = commentItemBinding.tvName;
        }

    }
}

自定义Dialog的使用

	public static void showRechargeAlertDialog(Context context, String title, int type, final OnSingleChoiceSelectedListener singleChoiceSelectedListener){
		//之前的写法
		View view = View.inflate(context, R.layout.dialog_recharge, null);
		TextView dialog_title = view.findViewById(R.id.dialog_title);
		dialog_title.setText("标题");
		final AlertDialog alertDialog = createAlertDialog(context, view, true);
		//使用viewbinding的写法
		DialogRechargeBinding binding = DialogRechargeBinding.inflate(LayoutInflater.from(context));
        binding.dialogTitle.setText("标题");
        final AlertDialog alertDialog = createAlertDialog(context, binding.getRoot(), true);
	}
	//创建共用的dialog的属性
    public static AlertDialog createAlertDialog(Context context, View view, boolean isCancelable){
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setView(view);
        final AlertDialog catDialog = builder.show();
        catDialog.setCancelable(isCancelable);//按返回键是否可以退出,true允许
        catDialog.getWindow().setBackgroundDrawable(null);
        catDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        WindowManager.LayoutParams lp = catDialog.getWindow().getAttributes();
        lp.width = SystemUtil.getScreenWidth(context); //设置宽度
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        catDialog.getWindow().setAttributes(lp);
        return catDialog;
    }

Popupwindow也是一样就不重复了。

使用的layout文件有include

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_money_income);
        ActivityMoneyIncomeBinding moneyIncomeBinding = ActivityMoneyIncomeBinding.bind(getContainer());;
		//如果include的布局是当前 module里的布局
		//就可以直接调用
		//moneyIncomeBinding.moneyView.title.setText("标题");
		//如果是其它module里的
		//那么需要在哪个module里开启viewbinding
		//调用方法
        View money_view = findViewById(R.id.money_view);
        MartianMoneyWithdrawViewBinding moneyBinding = MartianMoneyWithdrawViewBinding.bind(money_view);
		moneyBinding.title.setText("标题");
}
 类似资料: