android databind高级用法,Android DataBinding 使用及心得

DataBinding

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

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

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

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

1.如果你写过Js项目,想必双向绑定的印象肯定会特别深刻,而databinding在xml文件中的使用方式,将会让你更深刻

name="viewModel"

type="com.google.samples.apps.sunflower.viewmodels.PlantDetailViewModel" />

name="callback"

type="com.google.samples.apps.sunflower.PlantDetailFragment.Callback" />

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">

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> {

Context context;

public MessageAdapter(Context context, int layoutResId, @Nullable List data) {

super(layoutResId, data);

this.context = context;

}

@Override

protected void convert(@NotNull BaseDataBindingHolder 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,databind高级用法)