Android MVVM探索(ViewModel + LiveD

作者: 一位不愿透露自己姓氏的先生 | 来源:发表于2019-10-25 14:22 被阅读0次

本文是对ViewModel + LiveData + Databinding架构的一些探讨。

直接上代码:

ViewModel:

public class SplshViewModel extends BaseViewModel<SplashNavigator> {
MutableLiveData<PosterBean> data = new MutableLiveData();
PosterBean p = new PosterBean();
private DisposableSubscriber disposableSubscriber;

@Override
public void loadData() {
    RetrofitManager.getInstance().createReq(SplashApi.class)
            .getPoster()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new BaseObserver<PosterBean>() {
                @Override
                public void onSuccees(PosterBean posterBean) {
                    if (posterBean.getCode() != 0) {
                        getNavigator().showMessage(posterBean.getMessage());
                        return;
                    }
                    p.setCode(posterBean.getCode());
                    p.setData(posterBean.getData());
                    p.setMessage(posterBean.getMessage());
                    data.setValue(p);
                }
                @Override
                public void onFailure(String message) {
                    getNavigator().showMessage(message);
                }
            });

}



public LiveData<PosterBean> getData() {
    return data;
}


public void shipOnClick(View view) {
    getNavigator().openMainActivity();
}

public void posterOnClick(View view) {
  
}

public void startCount(int t) {
    disposableSubscriber = new DisposableSubscriber<Long>() {
        @Override
        public void onNext(Long aLong) {
            int time = (int) (t - aLong);
            getNavigator().upoutime(time);
        }
        @Override
        public void onError(Throwable t) {
            System.out.println(t.toString());
        }
        @Override
        public void onComplete() {
            getNavigator().openMainActivity();
        }
    };
    Flowable.interval(0, 1, TimeUnit.SECONDS, Schedulers.newThread())
            .take(t)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(disposableSubscriber);
}

@Override
protected void onCleared() {
    super.onCleared();
    if (disposableSubscriber != null)
        if (!disposableSubscriber.isDisposed()) {
            disposableSubscriber.dispose();
            disposableSubscriber = null;
        }
}

}

Activity:

public class SplashActivity extends BaseActivity<ActivitySplashBinding, SplshViewModel> implements SplashNavigator {
private boolean qz = false;
private AlertDialog.Builder normalDialog;
private AlertDialog dialog;

@Override
protected SplshViewModel getViewModel() {
    SplshViewModel splshViewModel = ViewModelProviders.of(this).get(SplshViewModel.class);
    return splshViewModel;
}

@Override
protected int getLayoutResId() {
    return R.layout.activity_splash;
}

@Override
protected void initView() {
    mViewModel.setNavigator(this);
    mViewModel.loadData();
    mViewModel.getData().observe(this, posterBean -> {
        mBinding.setViewModel(mViewModel);
        
    });


}




@Override
protected String getLogTag() {
    return "SplashActivity";
}

@Override
public void showMessage(String msg) {
    showToas(msg);
}

@Override
public void finsh() {
    finish();
}

@Override
public void openMainActivity() {
    if (qz) return;
    startActivity(new Intent(mContext, MainActivity.class));
    finish();
}

@Override
public void loadImage(String url) {
    mBinding.tvSkip.setVisibility(View.VISIBLE);
    Glide.with(mContext).load(url).into(mBinding.ivPoster);
}
}

XML:

 <?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context="com.xueseng.activity.SplashActivity">

<data>

    <import type="android.view.View" />
    <variable
        name="viewModel"
        type="com.xueseng.viewmodel.SplshViewModel" />
</data>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    >

    <ImageView
        android:id="@+id/iv_poster"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/color_white"
        android:scaleType="centerCrop"
        android:onClick="@{viewModel.posterOnClick}"
        android:src="@mipmap/lunchpage" />


    <TextView
        android:id="@+id/tv_skip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="40dp"
        android:background="@drawable/shape_splah_taks"
        android:paddingLeft="8dp"
        android:paddingTop="3dp"
        android:paddingRight="8dp"
        android:paddingBottom="3dp"
        android:onClick="@{viewModel.shipOnClick}"
        android:text="跳过 3"
        android:visibility="gone" />

</RelativeLayout>

</layout>
  • 解释

SplshViewModel的loadData()加载数据,getData获取数据,然后activity通过 mViewModel.getData().observe()订阅,数据变化时回调,然后通过 DataBindingUtil.setContentView(this, getLayoutResId());获取到databinding。(这段代码我封装在baseActivity当中了),最后通过mBinding.setViewModel(mViewModel);将数据和databinding绑定,我这里绑定的是viewModel,因为,我点击事件方法写在ViewModel当中的。

  • 问题
    相信这段代码大家都能看懂,但是有一个问题,我想把业务相关的代码放在ViewModel中处理,比如,开屏页展示的广告,我需要判断广告类型,控制跳转具体的页面。我定义了一个SplashNavigator接口,Activity实现该接口,然后通过mViewModel.setNavigator(this); ViewModel持有SplashNavigator,这时候ViewMdel处理完数据,然后通过SplashNavigator提供的具体的方法,具体的去控制页面跳转。这只是一个简单的需求,项目中或许需要更复杂的处理完数据后和activity交互。但是官方文档中说,ViewModel中最好不要持有Activity或者Context的引用,那么我想在ViewModel中处理业务和数据,Activity仅仅只负责更新UI。此时我应该怎么做呢?

我知道大部分数据可以通过DataBinding来和View进行绑定,还可以双向绑定,那比如我要showDialog、showToas、这种时候该怎么做呢?

  • 网上能找到的文章基本你抄我我超你,或者照着官方的几行代码写一小段,完全没有实际意义,希望有大神不吝赐教,共同探讨一下,感谢。

相关文章

网友评论

    本文标题:Android MVVM探索(ViewModel + LiveD

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