美文网首页
Android DataBinding 使用及心得

Android DataBinding 使用及心得

作者: 虞_18bd | 来源:发表于2020-12-30 23:13 被阅读0次

DataBinding

android UI 控件从xml文件的对象化存在大量的重复操作,相信每一个android开发者都经历过findViewById的阶段。

直到注解被重视后,通过注解省略findViewById这个流程变得简单了,我们最初是通过反射加注解在编译期完成注册,看上很像是ButterKnife

ButterKnife为了适配更多的场景,不仅仅使用了注解,还有注解处理器(annotationProcess)类似 APT(Annotation Processing Tool), 手机玩目标类基本信息后,再用JavaPoet生成Java类文件。

而我今天想说的DataBinding则给了Android开发者另外一种独特的体验:

1.如果你写过Js项目,想必双向绑定的印象肯定会特别深刻,而databinding在xml文件中的使用方式,将会让你更深刻
<data>
    <import type="com.google.samples.apps.sunflower.data.Plant"/>
    <variable
        name="viewModel"
        type="com.google.samples.apps.sunflower.viewmodels.PlantDetailViewModel" />
    <variable
        name="callback"
        type="com.google.samples.apps.sunflower.PlantDetailFragment.Callback" />
</data>

  <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/toolbar_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:contentScrim="?attr/colorSurface"
                app:statusBarScrim="?attr/colorSurface"
                app:collapsedTitleGravity="center"
            app:collapsedTitleTextAppearance="@style/TextAppearance.Sunflower.Toolbar.Text"
                app:layout_scrollFlags="scroll|exitUntilCollapsed"
                app:title="@{viewModel.plant.name}" // viewModel的这样使用是不是很特别
                app:titleEnabled="false"
                app:toolbarId="@id/toolbar">
      
              <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            style="@style/Widget.MaterialComponents.FloatingActionButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/fab_margin"
            android:onClick="@{() -> callback.add(viewModel.plant)}" // 甚至我的天 方法回调也能实现
            android:tint="@android:color/white"
            app:shapeAppearance="@style/ShapeAppearance.Sunflower.FAB"
            app:isFabGone="@{viewModel.isPlanted}"
            app:layout_anchor="@id/appbar"
            app:layout_anchorGravity="bottom|end"
            app:srcCompat="@drawable/ic_plus" />
2.上面那个例子可以让你惊讶它的双向绑定的能力,而下面则是释放双手
// RegisterActivity.java  实现注册功能

public class RegisterActivity extends MVVMActivity {

    private final static String TAG = "RegisterActivity";

    ActivityRegisterBinding mDataBinding;
    RegisterViewModel mViewModel;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void initViewModel() {
        mDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_register);
    }

    @Override
    public void init(){
        mLoading = new LoadingDialog.Builder(RegisterActivity.this);
        mLoading.setMessage(getString(R.string.register_loading));
        mLoading.create();
    }

    @Override
    public void bindUi(){
        // 点击上方关闭按钮
        RxView.clicks(mDataBinding.closeImg)
                .to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                .subscribe(unit -> finish());

        // 点击注册按钮
        RxView.clicks(mDataBinding.submitBtn)
                .to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                .subscribe(unit -> mViewModel.register(mDataBinding.registerUserNameEdt.getText().toString().trim()
                        , mDataBinding.registerPasswordEdt.getText().toString().trim()
                        , mDataBinding.repeatRegisterPasswordEdt.getText().toString().trim()));
    }

    @Override
    public void subscribeUi() {
        // 注册页面状态更变通知
        mViewModel.getRegisterState().observe(this, state -> {
            switch (state) {
                case ERROR_CUSTOMER_SUCCESS_PASS:
                    mLoading.getObj().show(); // 通过校验 开始网络请求
                    break;
                case ERROR_CUSTOMER_PASSWORD_ERROR: // 账号错误
                case ERROR_CUSTOMER_USERNAME_ERROR: // 密码错误
                case ERROR_CUSTOMER_REPEAT_ERROR: //   账号密码不一致
                    ToastUtil.showToast(this, TCErrorConstants.getErrorInfo(state));
                    break;

            }
        });

        // 注册接口回调通知
        LiveEventBus.get(RequestTags.REGISTER_REQ, BaseResponBean.class)
                .observe(this, bean -> {
                    Optional.ofNullable(mLoading).ifPresent(builder -> mLoading.getObj().dismiss());  // 取消 Loading
                    if (bean != null && bean.getCode() == 200) { //  注册成功 就开始自动登录
                        ToastUtil.showToast(RegisterActivity.this, "注册成功!");
                        mLoading.setMessage(getString(R.string.login_loading_text)).create().show();  // 显示登录中的loading
                        mViewModel.login(mDataBinding.registerUserNameEdt.getText().toString().trim() // 注册成功后 进行登录请求
                                , mDataBinding.registerPasswordEdt.getText().toString().trim());
                    } else {
                        ToastUtil.showToast(RegisterActivity.this, "注册失败:" + TCErrorConstants.getErrorInfo(bean.getCode()));
                    }
                });

        // 登录接口回调通知
        LiveEventBus.get(RequestTags.LOGIN_REQ, BaseResponBean.class)
                .observe(this, bean -> {
                    if (bean == null) return;
                    Optional.ofNullable(mLoading).ifPresent(builder -> mLoading.getObj().dismiss());  // 取消 Loading
                    if (bean.getCode() == 200) { // 登录成功
                        ToastUtil.showToast(this, "登录成功!");
                        startActivity(new Intent(RegisterActivity.this, MainActivity.class));
                        finish();
                    } else {                     // 登录失败
                        ToastUtil.showToast(this, "登录失败:" + TCErrorConstants.getErrorInfo(bean.getCode()));
                    }
                });
    }

    @Override
    public void initRequest() {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Optional.ofNullable(mLoading).ifPresent(builder -> mLoading.getObj().dismiss()); // 取消 Loading
    }
}

上面是我用DataBinding + ViewModel + LiveData + LiveDataBus + RxView 实现的一个注册功能

3.DataBinding在Adapter中的使用呢
// MessageAdapter.java

public class MessageAdapter extends BaseQuickAdapter<MessageItemBean, BaseDataBindingHolder<LayoutMessageSignBinding>> {

    Context context;

    public MessageAdapter(Context context, int layoutResId, @Nullable List<MessageItemBean> data) {
        super(layoutResId, data);
        this.context = context;
    }

    @Override
    protected void convert(@NotNull BaseDataBindingHolder<LayoutMessageSignBinding> layoutMessageSignBindingBaseDataBindingHolder, MessageItemBean messageItemBean) {
        LayoutMessageSignBinding binding = DataBindingUtil.getBinding(layoutMessageSignBindingBaseDataBindingHolder.itemView);
        if(binding == null || messageItemBean == null) return;
        binding.titleTv.setText(messageItemBean.getMessageTitle());
        binding.timeTv.setText(messageItemBean.getMessageTime());
        binding.messageContent.setText(messageItemBean.getMessageContent());
    }
}

上面是DataBinding + Bravh ,让Adapter变得无比简洁

4.这里说一下databinding的原理吧

首先,databinding会把xml拆分成数据和布局两部分 剩下的明天继续

相关文章

网友评论

      本文标题:Android DataBinding 使用及心得

      本文链接:https://www.haomeiwen.com/subject/hsfkoktx.html