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端實現 是不是很簡單~