移动架构47_视图绑定组件ViewBinding

Android移动架构汇总​​​​​​​

一、控件的声明

在Activity中绑定布局中的控件一般有三种实现方式:

  • 第一种用最原生态的findViewById方法来绑定
  • 第二种方式可以使用ButterKnife开源框架实现,ButterKnife对组件化的支持却很不友好
  • 第三种方式是使用Kotlin的扩展插件来获取视图控件,使用局限性:无法跨模块操作,类型不安全:不同的资源文件可以存在相同的控件id,因此在View层存在引用id来源出错的问题。

Kotlin 1.4版本中废弃了扩展插件,Google推荐使用ViewBinding来替代废弃的扩展插件

二、ViewBinding的基本使用

build.gradle中添加如下配置:

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

配置完成后,系统会为该模块中的每个XML布局文件生成一个绑定类,这个绑定类的命名就是XML文件的名称转换为驼峰式,并在末尾添加“Binding”一词,直接可以通过view binding这一中间类获取到xml中定义的view组件了

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_new_stock_bjs_records);
      viewBinding = ActivityNewStockBjsRecordsBinding.inflate(getLayoutInflater());
    
      viewBinding.navigationBar.setText("北交所新股申购")
    }

需要注意的一点是,开发者需要在onDestroyView()方法中将绑定类实例赋值为null。Fragment的存在时间比其视图时间长,所以开发者需要在onDestroyView()方法中清除对绑定类实例的所有引用,否则可能存在内存泄漏的风险

注意
如果某个布局文件不需要的话,可以通过tools:viewBinding-Ignore=“true”属性来设置

三、ViewBinding特点

  1. 集成简单
  2. 代码简洁,维护容易
  3. 对象空值安全:由于视图绑定会对视图直接引用,因此不存在因视图id无效而引发空指针异常的风险。
  4. 类型安全:每个绑定类中的字段均具有与它们在xml文件中引用的视图相匹配的类型,因此不存在强制转换可能导致的异常问题

四、ViewBinding的封装

ViewBinding组件的使用流程基本是固定的,主要分为三步:

  1. 调用生成的绑定类中的inflate()方法来获取绑定类的实例。
  2. 通过调用绑定类的getRoot()方法获取对根视图。
  3. 将根视图传递到setContentView()中,并与当前Activity绑定。
    由于ViewBinding使用的流程是固定的,因此在基础业务的开发中,经常会定义一个BaseActivity处理所有Activity的相同业务逻辑,这时,就可以将这部分逻辑封装在BaseActivity中
/**
 * 使用ViewBinding的基础类
 *
 * @param <T>
 */
public abstract class ViewBindingBaseActivity<T extends ViewBinding> extends ActivityBase {

    protected T mViewBinding;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mViewBinding = getViewBinding();
        setContentView(mViewBinding.getRoot());
    }

    /**
     * @return 返回Activity对于xml生成的ViewBinding对象
     */
     public abstract T getViewBinding();

}

五、源码

在项目模块的build.gradle中开启ViewBinding功能之后,若进行项目编译,就会扫描layout下所有的布局文件,并生成对应的绑定类(Project视图:
app/build/generated/data_binding_base_class_source_out/debug/out/包名/databinding路径下)。这一点是由gradle插件实现的

public final class ActivityTestBinding implements ViewBinding {
  @NonNull
  private final LinearLayout rootView;

  @NonNull
  public final ImageView imShezhi;

  @NonNull
  public final HomeRefresh reRefresh;

  @NonNull
  public final RecyclerView rv;

  @NonNull
  public final TextView tvName;

  private ActivityTestBinding(@NonNull LinearLayout rootView, @NonNull ImageView imShezhi,
      @NonNull HomeRefresh reRefresh, @NonNull RecyclerView rv, @NonNull TextView tvName) {
    this.rootView = rootView;
    this.imShezhi = imShezhi;
    this.reRefresh = reRefresh;
    this.rv = rv;
    this.tvName = tvName;
  }

  @Override
  @NonNull
  public LinearLayout getRoot() {
    return rootView;
  }

  @NonNull
  public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater) {
    return inflate(inflater, null, false);
  }

  @NonNull
  public static ActivityTestBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup parent, boolean attachToParent) {
    View root = inflater.inflate(R.layout.activity_test, parent, false);
    if (attachToParent) {
      parent.addView(root);
    }
    return bind(root);
  }

  @NonNull
  public static ActivityTestBinding 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.
    String missingId;
    missingId: {
      ImageView imShezhi = rootView.findViewById(R.id.im_shezhi);
      if (imShezhi == null) {
        missingId = "imShezhi";
        break missingId;
      }
      HomeRefresh reRefresh = rootView.findViewById(R.id.re_refresh);
      if (reRefresh == null) {
        missingId = "reRefresh";
        break missingId;
      }
      RecyclerView rv = rootView.findViewById(R.id.rv);
      if (rv == null) {
        missingId = "rv";
        break missingId;
      }
      TextView tvName = rootView.findViewById(R.id.tv_name);
      if (tvName == null) {
        missingId = "tvName";
        break missingId;
      }
      return new ActivityTestBinding((LinearLayout) rootView, imShezhi, reRefresh, rv, tvName);
    }
    throw new NullPointerException("Missing required view with ID: ".concat(missingId));
  }
}

从生成的ActivityTestBinding文件中可以轻松地看出,在调用了inflate之后会调用bind方法,而bind方法依然是通过findViewById绑定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您可以使用以下SQL语句来执行cs_student_view视图并查看结果: ``` SELECT * FROM cs_student_view; ``` 这将显示cs_student_view视图的所有内容。 ### 回答2: SQL语句执行cs_student_view视图并观察结果,需要先了解视图的概念。视图是一个虚拟的表,其内容由查询语句定义,可以将复杂的查询语句封装成视图以提高查询效率和简化查询操作。 首先,我们需要创建cs_student_view视图,可以使用CREATE VIEW语句来完成。这个视图的内容可能是从多个表中进行JOIN操作或者对单个表进行某些筛选条件的过滤。 假设我们创建的cs_student_view视图是从名为students和courses的两个表中获取学生姓名和所选课程的视图,那么执行SQL语句SELECT * FROM cs_student_view;将会返回包含学生姓名和所选课程的结果集。 在观察结果时,我们需要注意以下几点: 1. 视图的结果集是根据创建视图的查询语句动态生成的,并不是实际存储在数据库中的数据; 2. 执行视图查询语句时,数据库引擎会实时解析视图,将其转换为相关的SQL语句,然后在底层表上执行这些SQL语句来得到结果集; 3. 视图结果集的内容会随着基础表数据的更新而动态变化,即当基础表数据发生变化时,再次执行视图查询语句会得到最新的结果; 4. 视图可以嵌套,即在一个视图的定义中可以引用另外一个视图。 所以,在执行SQL语句SELECT * FROM cs_student_view;时,我们会得到由cs_student_view视图定义的结果集,其中包含学生姓名以及所选课程等相关信息。这个结果集的内容是根据视图查询语句的定义和基础表的数据通过实时查询动态生成的。 ### 回答3: 执行SQL语句``SELECT * FROM cs_student_view``可以获得cs_student_view视图的结果。视图是一种虚拟表,由一个或多个表查询所得到的结果集,可以像使用表一样进行操作。观察结果包括以下几方面: 1. 返回的结果集:执行语句后,会返回查询视图所得到的结果集。结果集可能包含多行和多列的数据,每一行代表一个记录,每一列代表一种数据类型。 2. 数据的准确性:通过观察结果集,可以判断视图查询的数据是否符合预期的要求。如果数据准确无误,说明视图定义和查询语句正确,数据被正确地筛选和组合。 3. 数据的完整性:视图查询可以使用WHERE子句等条件筛选数据,观察结果可以判断数据的完整性是否满足要求。如若某些记录被意外地包含或排除在结果集中,可能需要调整查询语句或重新定义视图来确保数据的完整性。 4. 性能优化:通过观察结果可以评估视图的查询性能,包括查询的执行时间、占用的系统资源等。如果查询时间过长或占用的资源过多,可能需要进一步优化查询语句或调整视图定义,以提高性能。 总之,通过执行SQL语句并观察结果,可以了解和评估cs_student_view视图的查询效果,进而根据需要对视图的定义和查询语句进行调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值