Android笔记之ViewModel的使用示例

依赖

implementation 'android.arch.lifecycle:extensions:1.1.1'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

android.arch.lifecycle:extensions:1.1.1用于引用ViewModelProviders

ViewModelProviders官方文档

Android笔记之ViewModel的使用示例

EyeKeyService.java

package com.bu_ish.viewmodeltest.service;

import com.bu_ish.viewmodeltest.reply.FaceCheckingReply;
import com.bu_ish.viewmodeltest.reply.FacesComparingReply;

import io.reactivex.Single;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;

public interface EyeKeyService {
    String BASE_URL = "http://api.eyekey.com/face/";
    String APP_ID = "f89ae61fd63d4a63842277e9144a6bd2";
    String APP_KEY = "af1cd33549c54b27ae24aeb041865da2";

    @FormUrlEncoded
    @POST("Check/checking")
    Single<FaceCheckingReply> checkFace(@Field("app_id") String appId, @Field("app_key") String appKey, @Field("url") String url);

    @GET("Match/match_compare")
    Single<FacesComparingReply> compareFaces(@Query("app_id") String appId, @Query("app_key") String appKey, @Query("face_id1") String faceId1, @Query("face_id2") String faceId2);
}

EyeKeyRepository.java

package com.bu_ish.viewmodeltest.view_model;

import com.bu_ish.viewmodeltest.service.EyeKeyService;
import com.bu_ish.viewmodeltest.reply.FaceCheckingReply;
import com.bu_ish.viewmodeltest.reply.FacesComparingReply;

import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class EyeKeyRepository {
    private static EyeKeyRepository instance = new EyeKeyRepository();
    private EyeKeyService service;

    private EyeKeyRepository() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(EyeKeyService.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        service = retrofit.create(EyeKeyService.class);
    }

    public static EyeKeyRepository getInstance() {
        return instance;
    }

    public Single<FaceCheckingReply> checkFace(String url) {
        return setScheduler(service.checkFace(EyeKeyService.APP_ID, EyeKeyService.APP_KEY, url));
    }

    public Single<FacesComparingReply> compareFaces(String faceId1, String faceId2) {
        return setScheduler(service.compareFaces(EyeKeyService.APP_ID, EyeKeyService.APP_KEY, faceId1, faceId2));
    }

    private Single setScheduler(Single single) {
        return single.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }
}

EyeKeyViewModel.java

package com.bu_ish.viewmodeltest.view_model;

import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

import com.bu_ish.viewmodeltest.observer.ReplyObserver;
import com.bu_ish.viewmodeltest.reply.FaceCheckingReply;
import com.bu_ish.viewmodeltest.reply.FacesComparingReply;

public class EyeKeyViewModel extends ViewModel {
    public MutableLiveData<FaceCheckingReply> faceCheckingReply1Data = new MutableLiveData<>();
    public MutableLiveData<FaceCheckingReply> faceCheckingReply2Data = new MutableLiveData<>();
    public MutableLiveData<FacesComparingReply> facesComparingReplyData = new MutableLiveData<>();
    private DialogViewModel dialogViewModel;
    private EyeKeyRepository eyeKeyRepository;

    public EyeKeyViewModel(DialogViewModel dialogViewModel) {
        this.dialogViewModel = dialogViewModel;
        eyeKeyRepository = EyeKeyRepository.getInstance();
    }

    public void checkFace1(String url) {
        eyeKeyRepository.checkFace(url).subscribe(new ReplyObserver<FaceCheckingReply>(dialogViewModel) {
            @Override
            public void onReply(FaceCheckingReply reply) {
                faceCheckingReply1Data.setValue(reply);
            }
        });
    }

    public void checkFace2(String url) {
        eyeKeyRepository.checkFace(url).subscribe(new ReplyObserver<FaceCheckingReply>(dialogViewModel) {
            @Override
            public void onReply(FaceCheckingReply reply) {
                faceCheckingReply2Data.setValue(reply);
            }
        });
    }

    public void compareFaces(String faceId1, String faceId2) {
        eyeKeyRepository.compareFaces(faceId1, faceId2).subscribe(new ReplyObserver<FacesComparingReply>(dialogViewModel) {
            @Override
            public void onReply(FacesComparingReply reply) {
                facesComparingReplyData.setValue(reply);
            }
        });
    }
}

ReplyObserver.java

package com.bu_ish.viewmodeltest.observer;

import com.bu_ish.viewmodeltest.reply.BaseReply;
import com.bu_ish.viewmodeltest.view_model.DialogViewModel;

import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;

public abstract class ReplyObserver<T extends BaseReply> implements SingleObserver<T> {
    public abstract void onReply(T reply);

    private DialogViewModel dialogViewModel;

    public ReplyObserver(DialogViewModel dialogViewModel) {
        this.dialogViewModel = dialogViewModel;
    }

    @Override
    public void onSubscribe(Disposable d) {
        dialogViewModel.showProgressData.setValue(true);
    }

    @Override
    public void onSuccess(T reply) {
        dialogViewModel.showProgressData.setValue(false);
        String code = reply.getResCode();
        if (code.equals("0000")) {
            onReply(reply);
        } else {
            dialogViewModel.showErrorData.setValue(reply);
        }
    }

    @Override
    public void onError(Throwable e) {
        dialogViewModel.showProgressData.setValue(false);
        dialogViewModel.showExceptionData.setValue(e);
    }
}

EyeKeyViewModelFactory.java

package com.bu_ish.viewmodeltest.view_model;

import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProvider;
import android.support.annotation.NonNull;

public class EyeKeyViewModelFactory implements ViewModelProvider.Factory {
    private DialogViewModel dialogViewModel;

    public EyeKeyViewModelFactory(DialogViewModel dialogViewModel) {
        this.dialogViewModel = dialogViewModel;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        return (T) new EyeKeyViewModel(dialogViewModel);
    }
}

DialogViewModel.java

package com.bu_ish.viewmodeltest.view_model;

import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

import com.bu_ish.viewmodeltest.reply.BaseReply;

public class DialogViewModel extends ViewModel {
    public MutableLiveData<Boolean> showProgressData = new MutableLiveData<>();
    public MutableLiveData<BaseReply> showErrorData = new MutableLiveData<>();
    public MutableLiveData<Throwable> showExceptionData = new MutableLiveData<>();
}

使用ViewModel的好处

即使发生配置变更(Configuration Change),ViewModel中的数据依然存在

所以,使用ViewModel后,也就不需要考虑onSaveInstanceState这类操作了^_^

参考博文

MVVM 架构,ViewModel和LiveData(一)

完整Demo

链接:https://pan.baidu.com/s/1TwY9OZTaQPk1eCn7vSz4fA,提取码:x0fy