refactor(mvvm): 重构 BaseViewModel 依赖注入并移除 ViewDataBindingCallback 接口
This commit is contained in:
1 parent
8a3ac6f5b4
commit
497af25e2e
13 files changed
+142
-165
No files matched your search
@@ -71,9 +71,6 @@ public class DebugActivity extends BaseMvvmActivity<DebugViewModel, ActivityDebu
|
||||
|
||||
@Override
|
||||
protected void initDataBinding() {
|
||||
mViewModel.setCtx(this);
|
||||
mViewModel.setLifecycle(getLifecycleSubject());
|
||||
mViewModel.setVDBinding(mViewDataBinding);
|
||||
mViewDataBinding.setClick(new BtnClick());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,17 +2,6 @@ package com.aoleyun.sn.activity.debug;
|
||||
|
||||
import com.aoleyun.sn.base.mvvm.BaseViewModel;
|
||||
import com.aoleyun.sn.databinding.ActivityDebugBinding;
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
|
||||
public class DebugViewModel extends BaseViewModel<ActivityDebugBinding, ActivityEvent> {
|
||||
|
||||
@Override
|
||||
public ActivityDebugBinding getVDBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
public class DebugViewModel extends BaseViewModel<ActivityDebugBinding> {
|
||||
}
|
||||
@@ -167,7 +167,7 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_main;
|
||||
}
|
||||
|
||||
@@ -178,14 +178,11 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
||||
|
||||
@Override
|
||||
protected void initDataBinding() {
|
||||
mViewModel.setCtx(this);
|
||||
mViewModel.setLifecycle(getLifecycleSubject());
|
||||
mViewModel.setVDBinding(mViewDataBinding);
|
||||
mViewDataBinding.setClick(new BtnClick());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initView() {
|
||||
protected void initView() {
|
||||
if (BuildConfig.DEBUG) {
|
||||
// Uri uri = Uri.parse("https://www.baidu.com");
|
||||
// Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
@@ -371,7 +368,7 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initData() {
|
||||
protected void initData() {
|
||||
Log.e("getMacAddress", Utils.getAndroid10MAC(this));
|
||||
Intent intent = new Intent(MainActivity.this, MainService.class);
|
||||
bindService(intent, serviceConnect, BIND_AUTO_CREATE);
|
||||
|
||||
@@ -41,19 +41,9 @@ import io.reactivex.rxjava3.core.Observer;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEvent> {
|
||||
public class MainViewModel extends BaseViewModel<ActivityMainBinding> {
|
||||
private static final String TAG = "MainViewModel";
|
||||
|
||||
@Override
|
||||
public ActivityMainBinding getVDBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
|
||||
public void init() {
|
||||
checkUpdateInfo();
|
||||
checkAoleyunUpdate();
|
||||
|
||||
@@ -19,7 +19,7 @@ public class RequestLogActivity extends BaseMvvmActivity<RequestLogViewModel, Ac
|
||||
private RequestLogAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_request_log;
|
||||
}
|
||||
|
||||
@@ -30,21 +30,18 @@ public class RequestLogActivity extends BaseMvvmActivity<RequestLogViewModel, Ac
|
||||
|
||||
@Override
|
||||
protected void initDataBinding() {
|
||||
mViewModel.setCtx(this);
|
||||
mViewModel.setLifecycle(getLifecycleSubject());
|
||||
mViewModel.setVDBinding(mViewDataBinding);
|
||||
mViewDataBinding.setClick(new BtnClick());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initView() {
|
||||
protected void initView() {
|
||||
mViewDataBinding.recyclerview.setLayoutManager(new LinearLayoutManager(this));
|
||||
mAdapter = new RequestLogAdapter();
|
||||
mViewDataBinding.recyclerview.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initData() {
|
||||
protected void initData() {
|
||||
mViewModel.getLogBeanListData().observe(this, new Observer<List<LogBean>>() {
|
||||
@Override
|
||||
public void onChanged(List<LogBean> logBeans) {
|
||||
|
||||
@@ -6,29 +6,18 @@ import com.aoleyun.sn.base.mvvm.BaseViewModel;
|
||||
import com.aoleyun.sn.databinding.ActivityRequestLogBinding;
|
||||
import com.aoleyun.sn.rlog.LogBean;
|
||||
import com.aoleyun.sn.rlog.LogDBManager;
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RequestLogViewModel extends BaseViewModel<ActivityRequestLogBinding, ActivityEvent> {
|
||||
public class RequestLogViewModel extends BaseViewModel<ActivityRequestLogBinding> {
|
||||
|
||||
@Override
|
||||
public ActivityRequestLogBinding getVDBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
|
||||
private MutableLiveData<List<LogBean>> mLogBeanListData =new MutableLiveData<>();
|
||||
private final MutableLiveData<List<LogBean>> mLogBeanListData = new MutableLiveData<>();
|
||||
|
||||
public MutableLiveData<List<LogBean>> getLogBeanListData() {
|
||||
return mLogBeanListData;
|
||||
}
|
||||
|
||||
public void getDBList(){
|
||||
public void getDBList() {
|
||||
mLogBeanListData.setValue(LogDBManager.getInstance().getLogList());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.aoleyun.sn.activity.update;
|
||||
|
||||
import static com.arialyy.aria.core.inf.IEntity.STATE_RUNNING;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
@@ -17,8 +19,6 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.hjq.toast.Toaster;
|
||||
|
||||
import static com.arialyy.aria.core.inf.IEntity.STATE_RUNNING;
|
||||
|
||||
public class AppUpdateActivity extends BaseMvvmActivity<AppUpdateViewModel, ActivityAppUpdateBinding> {
|
||||
|
||||
private AppUpdateInfo mAppInfoData;
|
||||
@@ -31,9 +31,6 @@ public class AppUpdateActivity extends BaseMvvmActivity<AppUpdateViewModel, Acti
|
||||
|
||||
@Override
|
||||
protected void initDataBinding() {
|
||||
mViewModel.setCtx(this);
|
||||
mViewModel.setLifecycle(getLifecycleSubject());
|
||||
mViewModel.setVDBinding(mViewDataBinding);
|
||||
mViewDataBinding.setClick(new BtnClick());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
package com.aoleyun.sn.activity.update;
|
||||
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
import com.aoleyun.sn.base.mvvm.BaseViewModel;
|
||||
import com.aoleyun.sn.databinding.ActivityAppUpdateBinding;
|
||||
|
||||
public class AppUpdateViewModel extends BaseViewModel<ActivityAppUpdateBinding, ActivityEvent> {
|
||||
|
||||
@Override
|
||||
public ActivityAppUpdateBinding getVDBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
public class AppUpdateViewModel extends BaseViewModel<ActivityAppUpdateBinding> {
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class UpdateActivity extends BaseMvvmActivity<UpdateViewModel, ActivityUp
|
||||
private AppUpdateAdapter mAppUpdateAdapter;
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_update;
|
||||
}
|
||||
|
||||
@@ -36,21 +36,18 @@ public class UpdateActivity extends BaseMvvmActivity<UpdateViewModel, ActivityUp
|
||||
|
||||
@Override
|
||||
protected void initDataBinding() {
|
||||
mViewModel.setCtx(this);
|
||||
mViewModel.setLifecycle(getLifecycleSubject());
|
||||
mViewModel.setVDBinding(mViewDataBinding);
|
||||
mViewDataBinding.setClick(new BtnClick());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initView() {
|
||||
protected void initView() {
|
||||
mAppUpdateAdapter = new AppUpdateAdapter();
|
||||
mViewDataBinding.recyclerView.setLayoutManager(new LinearLayoutManager(UpdateActivity.this));
|
||||
mViewDataBinding.recyclerView.setAdapter(mAppUpdateAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initData() {
|
||||
protected void initData() {
|
||||
mViewModel.getAppUpdateInfoListData().observe(this, new Observer<List<AppUpdateInfo>>() {
|
||||
@Override
|
||||
public void onChanged(List<AppUpdateInfo> appUpdateInfos) {
|
||||
|
||||
@@ -6,23 +6,12 @@ import com.aoleyun.sn.base.mvvm.BaseViewModel;
|
||||
import com.aoleyun.sn.bean.AppUpdateInfo;
|
||||
import com.aoleyun.sn.databinding.ActivityUpdateBinding;
|
||||
import com.aoleyun.sn.network.NetInterfaceManager;
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UpdateViewModel extends BaseViewModel<ActivityUpdateBinding, ActivityEvent> {
|
||||
public class UpdateViewModel extends BaseViewModel<ActivityUpdateBinding> {
|
||||
|
||||
@Override
|
||||
public ActivityUpdateBinding getVDBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
|
||||
private MutableLiveData<List<AppUpdateInfo>> mAppUpdateInfoListData = new MutableLiveData<>();
|
||||
private final MutableLiveData<List<AppUpdateInfo>> mAppUpdateInfoListData = new MutableLiveData<>();
|
||||
|
||||
public MutableLiveData<List<AppUpdateInfo>> getAppUpdateInfoListData() {
|
||||
return mAppUpdateInfoListData;
|
||||
|
||||
@@ -1,45 +1,91 @@
|
||||
package com.aoleyun.sn.base.mvvm;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.databinding.ViewDataBinding;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.aoleyun.sn.base.BaseTransparentActivity;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public abstract class BaseMvvmActivity<VM extends ViewModel, VDB extends ViewDataBinding> extends BaseTransparentActivity {
|
||||
private static final String TAG = "BaseMvvmActivity";
|
||||
/**
|
||||
* MVVM Activity 基类。
|
||||
*
|
||||
* <p>子类按 {@code BaseMvvmActivity<VM, VDB>} 声明泛型后,基类会在 onCreate 中自动完成:</p>
|
||||
* <ul>
|
||||
* <li>加载布局并创建 ViewDataBinding,设置 lifecycleOwner;</li>
|
||||
* <li>通过 ViewModelProvider 创建并复用 ViewModel;</li>
|
||||
* <li>为 ViewModel 注入 Binding / Application Context / 页面生命周期。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <VM> 页面 ViewModel,必须继承 {@link BaseViewModel}
|
||||
* @param <VDB> 页面 ViewDataBinding
|
||||
*/
|
||||
public abstract class BaseMvvmActivity<VM extends BaseViewModel<VDB>, VDB extends ViewDataBinding>
|
||||
extends BaseTransparentActivity {
|
||||
|
||||
protected VM mViewModel;
|
||||
protected VDB mViewDataBinding;
|
||||
protected Class<VM> vmClass;
|
||||
|
||||
@Override
|
||||
@CallSuper
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//ViewDataBinding
|
||||
|
||||
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
|
||||
mViewDataBinding.setLifecycleOwner(this);
|
||||
//ViewModel
|
||||
vmClass = (Class<VM>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
||||
boolean isAbstract = Modifier.isAbstract(vmClass.getModifiers());
|
||||
Log.e(TAG, "isLocalClass:" + vmClass.getSimpleName().equals(ViewModel.class.getSimpleName()) + " isAbstract:" + isAbstract);
|
||||
if (!isAbstract) {//不是一个抽象类
|
||||
mViewModel = new ViewModelProvider(this).get(vmClass);
|
||||
}
|
||||
|
||||
mViewModel = new ViewModelProvider(this).get(resolveViewModelClass());
|
||||
mViewModel.attach(mViewDataBinding, this, getLifecycleSubject());
|
||||
|
||||
initDataBinding();
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
protected abstract void initDataBinding();
|
||||
@Override
|
||||
@CallSuper
|
||||
protected void onDestroy() {
|
||||
if (mViewModel != null) {
|
||||
mViewModel.detach(mViewDataBinding);
|
||||
}
|
||||
mViewDataBinding = null;
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从泛型声明中解析 ViewModel 类型,支持子类之间存在多层继承。
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<VM> resolveViewModelClass() {
|
||||
Class<?> clazz = getClass();
|
||||
while (clazz != null && clazz != BaseMvvmActivity.class) {
|
||||
Type genericSuperclass = clazz.getGenericSuperclass();
|
||||
if (genericSuperclass instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
|
||||
if (parameterizedType.getRawType() == BaseMvvmActivity.class) {
|
||||
Type[] typeArguments = parameterizedType.getActualTypeArguments();
|
||||
if (typeArguments[0] instanceof Class) {
|
||||
return (Class<VM>) typeArguments[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
throw new IllegalStateException("无法解析 ViewModel 类型,请检查 "
|
||||
+ getClass().getName() + " 是否声明为 BaseMvvmActivity<VM, VDB>");
|
||||
}
|
||||
|
||||
/**
|
||||
* binding 相关初始化(如 setClick / setXxx),此时 ViewModel 已完成注入
|
||||
*/
|
||||
protected void initDataBinding() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化视图
|
||||
|
||||
@@ -2,70 +2,92 @@ package com.aoleyun.sn.base.mvvm;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.databinding.ViewDataBinding;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||
|
||||
/**
|
||||
* 所有viewmodel的基类
|
||||
* 所有 ViewModel 的基类。
|
||||
*
|
||||
* <p>Binding、Application Context、页面生命周期均由 {@link BaseMvvmActivity}
|
||||
* 在 onCreate 时自动注入,子类无需(也不应该)手动设置这些依赖。</p>
|
||||
*
|
||||
* @param <VDB> 该 ViewModel 对应的 ViewDataBinding 类型
|
||||
*/
|
||||
public abstract class BaseViewModel<VDB extends ViewDataBinding, T> extends ViewModel implements ViewDataBindingCallback {
|
||||
public abstract class BaseViewModel<VDB extends ViewDataBinding> extends ViewModel {
|
||||
|
||||
/**
|
||||
* 当前viewmodel对应的页面binding
|
||||
* 当前页面 binding,页面销毁时会被置空
|
||||
*/
|
||||
protected VDB binding;
|
||||
@Nullable
|
||||
private VDB binding;
|
||||
|
||||
@Override
|
||||
public void setVDBinding(ViewDataBinding vdBinding) {
|
||||
/**
|
||||
* Application Context,避免持有 Activity 造成内存泄漏
|
||||
*/
|
||||
@Nullable
|
||||
private Context appContext;
|
||||
|
||||
binding = (VDB) vdBinding;
|
||||
/**
|
||||
* 页面生命周期(RxLifecycle)
|
||||
*/
|
||||
@Nullable
|
||||
private BehaviorSubject<ActivityEvent> lifecycleSubject;
|
||||
|
||||
/**
|
||||
* 由 {@link BaseMvvmActivity} 调用,完成依赖注入。
|
||||
*/
|
||||
final void attach(@NonNull VDB binding,
|
||||
@NonNull Context context,
|
||||
@NonNull BehaviorSubject<ActivityEvent> lifecycleSubject) {
|
||||
this.binding = binding;
|
||||
this.appContext = context.getApplicationContext();
|
||||
this.lifecycleSubject = lifecycleSubject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VDB getVDBinding() {
|
||||
if (binding == null) {
|
||||
throw new NullPointerException("BaseViewModel >> getVDBinding >> null!!!");
|
||||
/**
|
||||
* 页面销毁时解除 binding 引用,避免 ViewModel 在配置变更后持有已销毁的视图。
|
||||
*/
|
||||
final void detach(@Nullable VDB vdBinding) {
|
||||
if (this.binding == vdBinding) {
|
||||
this.binding = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 当前页面 binding,页面销毁后返回 null
|
||||
*/
|
||||
@Nullable
|
||||
public final VDB getBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Application Context,ViewModel 被回收后返回 null
|
||||
*/
|
||||
@Nullable
|
||||
public final Context getCtx() {
|
||||
return appContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上下文
|
||||
* @return 页面生命周期,用于 RxLifecycle 绑定
|
||||
*/
|
||||
private WeakReference<Context> ctx;
|
||||
|
||||
@Override
|
||||
public void setCtx(Context context) {
|
||||
if (ctx == null) {
|
||||
ctx = new WeakReference<>(context);
|
||||
}
|
||||
@Nullable
|
||||
public final BehaviorSubject<ActivityEvent> getLifecycle() {
|
||||
return lifecycleSubject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getCtx() {
|
||||
if (ctx == null) {
|
||||
throw new NullPointerException("BaseViewModel >> getCtx >> null!!!");
|
||||
}
|
||||
return ctx.get();
|
||||
}
|
||||
|
||||
|
||||
public abstract void onDestroy();
|
||||
|
||||
private BehaviorSubject<T> mBehaviorSubject;
|
||||
|
||||
@Override
|
||||
public void setLifecycle(BehaviorSubject subject) {
|
||||
this.mBehaviorSubject = (BehaviorSubject<T>) subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviorSubject<T> getLifecycle() {
|
||||
return mBehaviorSubject;
|
||||
protected void onCleared() {
|
||||
binding = null;
|
||||
appContext = null;
|
||||
lifecycleSubject = null;
|
||||
super.onCleared();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.aoleyun.sn.base.mvvm;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.databinding.ViewDataBinding;
|
||||
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||
|
||||
public interface ViewDataBindingCallback<VDB extends ViewDataBinding, T> {
|
||||
|
||||
void setVDBinding(VDB binding);
|
||||
|
||||
VDB getVDBinding() throws NullPointerException;
|
||||
|
||||
void setCtx(Context context);
|
||||
|
||||
Context getCtx() throws NullPointerException;
|
||||
|
||||
void setLifecycle(BehaviorSubject<T> subject);
|
||||
|
||||
BehaviorSubject<T> getLifecycle();
|
||||
}
|
||||
Reference in new issue
Block a user