簡單創建Android MVVM模式代碼




import android.Manifest;
import android.Manifest.permission;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.WindowManager;

import com.afollestad.materialdialogs.MaterialDialog;
import com.elvishew.xlog.BuildConfig;
import com.elvishew.xlog.XLog;
import com.hexavii.core.R;
import com.hexavii.core.arch.base.livedata.DataState;
import com.hexavii.core.arch.base.viewmodel.BasicAndroidViewModel;
import com.hexavii.core.arch.base.viewmodel.BasicViewModel;
import com.hexavii.core.arch.tools.permission.RxPermissions;
import com.hexavii.core.arch.utils.ToastUtil;

import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import androidx.core.app.TaskStackBuilder;
import androidx.lifecycle.ViewModel;
import io.reactivex.Observable;

public abstract class BaseActivity<VM extends ViewModel> extends AppCompatActivity implements
  IBasicUIProcess<VM> {

  protected static final boolean DEBUG = BuildConfig.DEBUG;

  private VM mViewModel;
  protected boolean isPad = false;
  private MaterialDialog mDialog;

  @CallSuper
  @Override
  protected void onCreate(Bundle savedInstanceState) {
//    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
      WindowManager.LayoutParams.FLAG_FULLSCREEN);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    requestPermissions();

    if (DEBUG) {
      XLog.d(getLocalClassName() + ":" + savedInstanceState);
    }
    isPad = getResources().getBoolean(R.bool.is_pad);
    //頁面接受的參數方法
    initParam(savedInstanceState);
    mViewModel = getViewModel();
    initView(mViewModel);
    //頁面數據初始化方法
    initData(savedInstanceState, mViewModel);
    //頁面事件監聽的方法,一般用於ViewModel層轉到View層的事件註冊
    initViewObservable(mViewModel);
  }

  // 請求權限
  @SuppressLint("CheckResult")
  public void requestPermissions() {
    RxPermissions perm = RxPermissions.with(this);
    Observable<Boolean> observable;
    if (VERSION.SDK_INT >= VERSION_CODES.P) {
      observable = perm.request(permission.FOREGROUND_SERVICE, permission.CAMERA,
        permission.READ_PHONE_STATE,
        permission.READ_EXTERNAL_STORAGE, permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.DISABLE_KEYGUARD);
    } else {
      observable = perm.request(permission.CAMERA, permission.READ_PHONE_STATE,
        permission.READ_EXTERNAL_STORAGE, permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.DISABLE_KEYGUARD);
    }
    observable.doOnNext(granted -> {
      if (!granted) {
        XLog.i("權限未申請");
        ToastUtil.showLongToast(BaseActivity.this, "應用必要權限未授予");
      }
      onPermissionsGranted(granted);
    }).subscribe();
  }

  protected void onPermissionsGranted(boolean granted) {}

  @Override
  protected void onNewIntent(final Intent intent) {
    super.onNewIntent(intent);
    if (DEBUG) {
      XLog.d("onNewIntent: " + getLocalClassName());
    }
  }

  @Override
  protected void onRestart() {
    super.onRestart();
    if (DEBUG) {
      XLog.d("onRestart: " + getLocalClassName());
    }
  }

  @CallSuper
  @Override
  protected void onStart() {
    super.onStart();
    if (DEBUG) {
      XLog.d("onStart: " + getLocalClassName());
    }
  }

  @Override
  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (DEBUG) {
      XLog.d("onRestoreInstanceState: " + getLocalClassName());
    }
  }

  @CallSuper
  @Override
  protected void onResume() {
    super.onResume();
    if (DEBUG) {
      XLog.d("resume: " + getLocalClassName());
    }
  }

  @CallSuper
  @Override
  protected void onPause() {
    super.onPause();
    if (DEBUG) {
      XLog.d("stop: " + getLocalClassName());
    }
  }

  @Override
  protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    if (DEBUG) {
      XLog.d("onSaveInstanceState: " + getLocalClassName());
    }
  }

  @Override
  protected void onStop() {
    super.onStop();
    if (DEBUG) {
      XLog.d("stop: " + getLocalClassName());
    }
  }

  @CallSuper
  @Override
  protected void onDestroy() {
    super.onDestroy();
    if (DEBUG) {
      XLog.d("onDestroy: " + getLocalClassName());
    }
    // 解除ViewModel生命週期感應
    ViewModel vm = getViewModel();
    if (null != vm) {
      if (vm instanceof BasicViewModel) {
        getLifecycle().removeObserver((BasicViewModel) vm);
      } else if (vm instanceof BasicAndroidViewModel) {
        getLifecycle().removeObserver((BasicAndroidViewModel) vm);
      }
    }

    mViewModel = null;
    if (null != mDialog) {
      mDialog.dismiss();
      mDialog = null;
    }
  }

  @Override
  public VM createViewModel() {
    return null;
  }

  @Override
  public void initView(VM vm) {
  }

  @Override
  public void initParam(@Nullable final Bundle savedInstanceState) {
  }

  @Override
  public void initData(Bundle savedInstanceState, VM vm) {
  }

  public VM getViewModel() {
    if (null == mViewModel) {
      mViewModel = createViewModel();
    }
    return mViewModel;
  }

  @Override
  public void initViewObservable(VM vm) {
    if (null != vm) {
      if (vm instanceof BasicViewModel) {
        registerStateCallBack(((BasicViewModel) vm).getState());
        // 讓ViewModel擁有View的生命週期感應
        getLifecycle().addObserver((BasicViewModel) vm);
      } else if (vm instanceof BasicAndroidViewModel) {
        registerStateCallBack(((BasicAndroidViewModel) vm).getState());
        // 讓ViewModel擁有View的生命週期感應
        getLifecycle().addObserver((BasicAndroidViewModel) vm);
      }
    }
  }

  protected void registerStateCallBack(DataState state) {
    state.observe(this, this::onStateChanged);
  }

  protected void onStateChanged(Integer state) {
    if (null != mDialog) {
      mDialog.dismiss();
      mDialog = null;
    }
    switch (state) {
      case DataState.DIALOG_LOADING:
        mDialog = new MaterialDialog.Builder(this)
          .content(R.string.api_loading)
          .progress(true, 0).show();
        break;
      case DataState.CONTENT:
        break;
      case DataState.EMPTY:
        break;
      case DataState.ERROR:
        break;
      case DataState.ACTIVITY_FINISHED:
        finish();
        break;
    }
  }

  /**
   * 跳轉頁面
   *
   * @param clz
   *     所跳轉的目的Activity類
   */
  public void startActivity(Class<?> clz) {
    startActivity(new Intent(this, clz));
  }

  /**
   * 跳轉頁面
   *
   * @param clz
   *     所跳轉的目的Activity類
   * @param bundle
   *     跳轉所攜帶的信息
   */
  public void startActivity(Class<?> clz, Bundle bundle) {
    Intent intent = new Intent(this, clz);
    if (bundle != null) {
      intent.putExtras(bundle);
    }
    startActivity(intent);
  }

  /**
   * 跳轉容器頁面
   *
   * @param canonicalName
   *     規範名 : Fragment.class.getCanonicalName()
   */
  public void startContainerActivity(String canonicalName) {
    startContainerActivity(canonicalName, null);
  }

  /**
   * 跳轉容器頁面
   *
   * @param canonicalName
   *     規範名 : Fragment.class.getCanonicalName()
   * @param bundle
   *     跳轉所攜帶的信息
   */
  public void startContainerActivity(String canonicalName, Bundle bundle) {
    Intent intent = new Intent(this, ContainerActivity.class);
    intent.putExtra(ContainerActivity.FRAGMENT, canonicalName);
    if (bundle != null) {
      intent.putExtra(ContainerActivity.BUNDLE, bundle);
    }
    startActivity(intent);
  }

  protected void setDisplayHomeAsUpEnable(boolean enable) {
    // Show the Up button in the action bar.
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
      actionBar.setDisplayHomeAsUpEnabled(enable);
    }
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == android.R.id.home) {
      Intent upIntent = NavUtils.getParentActivityIntent(this);
      if (null == upIntent) {
        finish();
      } else if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
        // This activity is NOT part of this app's task, so create a new task
        // when navigating up, with a synthesized back stack.
        TaskStackBuilder.create(this)
                        // Add all of this activity's parents to the back stack
                        .addNextIntentWithParentStack(upIntent)
                        // Navigate up to the closest parent
                        .startActivities();
      } else {
        // This activity is part of this app's task, so simply
        // navigate up to the logical parent activity.
        NavUtils.navigateUpTo(this, upIntent);
      }
      return true;
    }
    return super.onOptionsItemSelected(item);
  }

  @Override
  public void startActivity(final Intent intent) {
    super.startActivity(intent);
    overridePendingTransition(R.anim.fade_out, R.anim.fade_in);
  }
}

BaseActivity創建新的類依賴於它

然後創建BAsicViewModel




import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class BasicViewModel extends ViewModel implements IBasicViewModel {

  private DataState mState;
  private MutableLiveData<String> mTitle;

  public DataState getState() {
    if (mState == null) {
      mState = DataState.getInstance();
    }
    return mState;
  }

  public MutableLiveData<String> getNavTitle() {
    if (mTitle == null) {
      mTitle = new MutableLiveData<>();
    }
    return mTitle;
  }

  @Override
  public void onAny(LifecycleOwner owner, Lifecycle.Event event) {
  }

  @Override
  public void onCreate() {
  }

  @Override
  public void onDestroy() {
  }

  @Override
  public void onStart() {
  }

  @Override
  public void onStop() {
  }

  @Override
  public void onResume() {
  }

  @Override
  public void onPause() {
  }
}

DataState類



import androidx.lifecycle.MutableLiveData;

public class DataState extends MutableLiveData<Integer> {

  public static final int ACTIVITY_FINISHED = -2;
  public static final int DIALOG_LOADING = -1;
  public static final int LOADING = 0;
  public static final int CONTENT = 2;
  public static final int EMPTY = 3;
  public static final int ERROR = 4;

  public void setActivityFinished() {
    setValue(ACTIVITY_FINISHED);
  }

  public void postActivityFinished() {
    postValue(ACTIVITY_FINISHED);
  }

  public void setDialogLoading() {
    setValue(DIALOG_LOADING);
  }

  public void postDialogLoading() {
    postValue(DIALOG_LOADING);
  }

  public void setLoading() {
    setValue(LOADING);
  }

  public void postLoading() {
    postValue(LOADING);
  }

  public void setContent() {
    setValue(CONTENT);
  }

  public void postContent() {
    postValue(CONTENT);
  }

  public void setEmpty() {
    setValue(EMPTY);
  }

  public void postEmpty() {
    postValue(EMPTY);
  }

  public void setError() {
    setValue(ERROR);
  }

  public void postError() {
    postValue(ERROR);
  }

  public static DataState getInstance() {
    return new DataState();
  }
}

 

然後在activity_xxxml中設置

<layout> 
 <data>

    <import type="android.view.View" />

    <import type="android.view.Gravity" />

    <import type="com.hexavii.facepassage.compare.viewmodel.FaceCompareViewModel" />

    <variable
      name="viewModel"
      type="FaceCompareViewModel" />
  </data>
</layput>


這段代碼一定要在<layout>標籤裏面

主界面Activity可以這麼寫

package com.hexavii.facepassage.compare.ui;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;

import com.hexavii.core.arch.base.BaseActivity;
import com.hexavii.core.arch.tools.systemui.SystemUiHelper;
import com.hexavii.facepassage.R;
import com.hexavii.facepassage.compare.viewmodel.FaceCompareViewModel;
import com.hexavii.facepassage.databinding.ActivityFaceCompareBinding;


public class FaceCompareActivity   extends BaseActivity<FaceCompareViewModel> {
  public static void start(Context context,int value) {
    Intent starter = new Intent(context, FaceCompareActivity.class);
    starter.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
      | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    starter.putExtra("type",value);
    context.startActivity(starter);
  }

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

  @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    if (hasFocus) {
      SystemUiHelper uiHelper = new SystemUiHelper(this, SystemUiHelper.LEVEL_IMMERSIVE,
        SystemUiHelper.FLAG_IMMERSIVE_STICKY);
      uiHelper.hide();
    }
  }

  @Override
  public void initView(FaceCompareViewModel faceCompareViewModel) {
    ActivityFaceCompareBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_face_compare);
    binding.setViewModel(getViewModel());
    binding.setLifecycleOwner(this);

  }

  @Override
  public void initData(Bundle savedInstanceState, FaceCompareViewModel faceCompareViewModel) {
    super.initData(savedInstanceState, faceCompareViewModel);
  }

  @Override
  public FaceCompareViewModel createViewModel() {
    return new ViewModelProvider(this).get(FaceCompareViewModel.class);
  }

  @Override
  public void initViewObservable(FaceCompareViewModel vm) {
    super.initViewObservable(vm);
    vm.getCheckState().observe(this, state -> {
      if (null == state ) {
        return;
      }

    });
  }
}

viewModel這麼實現

package com.hexavii.facepassage.compare.viewmodel;

import androidx.lifecycle.MutableLiveData;

import com.hexavii.core.arch.base.viewmodel.BasicViewModel;

public class FaceCompareViewModel extends BasicViewModel {
  private MutableLiveData<Integer> mCheckState = new MutableLiveData<>();
  public MutableLiveData<Integer> getCheckState() {
    return mCheckState;
  }
}

然後就可以設置xml中的實現了

以下爲MVVM 模式 Android端實現 是不是很簡單~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章