package com.doumee.lib_coremodel.base;
|
|
import android.app.Dialog;
|
import android.content.Context;
|
import android.content.Intent;
|
import android.graphics.Color;
|
import android.graphics.drawable.ColorDrawable;
|
import android.os.Bundle;
|
import android.os.Message;
|
import android.util.DisplayMetrics;
|
import android.view.LayoutInflater;
|
import android.view.View;
|
import android.view.ViewGroup;
|
import android.view.Window;
|
import android.view.WindowManager;
|
import android.widget.PopupWindow;
|
|
import androidx.annotation.IdRes;
|
import androidx.annotation.LayoutRes;
|
import androidx.annotation.NonNull;
|
import androidx.annotation.Nullable;
|
import androidx.core.app.ActivityOptionsCompat;
|
import androidx.databinding.DataBindingUtil;
|
import androidx.databinding.ViewDataBinding;
|
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.FragmentManager;
|
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelStoreOwner;
|
|
import com.doumee.lib_coremodel.R;
|
import com.doumee.lib_coremodel.base.livedata.MessageEvent;
|
import com.doumee.lib_coremodel.base.livedata.StatusEvent;
|
|
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.Type;
|
|
|
/**
|
* MVVMFrame 框架基于Google官方的 JetPack 构建,在使用MVVMFrame时,需遵循一些规范:
|
*
|
* 如果您继承使用了BaseDialogFragment或其子类,你需要参照如下方式添加@AndroidEntryPoint注解
|
*
|
* @example Fragment
|
* //-------------------------
|
* @AndroidEntryPoint
|
* public class YourFragment extends BaseDialogFragment {
|
*
|
* }
|
* //-------------------------
|
*
|
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
*/
|
public abstract class BaseDialogFragment<VM extends BaseViewModel,VDB extends ViewDataBinding> extends DialogFragment implements IView<VM>, BaseNavigator {
|
|
/**
|
* 请通过 {@link #getVM()}获取,后续版本 {@link #mViewModel}可能会私有化
|
*/
|
private VM mViewModel;
|
/**
|
* 请通过 {@link #getDB()}获取,后续版本 {@link #mBinding}可能会私有化
|
*/
|
private VDB mBinding;
|
/**
|
* 请通过 {@link #getRootView()} ()}获取,后续版本 {@link #mRootView}可能会私有化
|
*/
|
private View mRootView;
|
|
protected static final float DEFAULT_WIDTH_RATIO = 0.85f;
|
|
private Dialog mProgressDialog;
|
|
@Override
|
public void onAttach(Context context) {
|
super.onAttach(context);
|
}
|
|
@Nullable
|
@Override
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
initDialog(getDialog());
|
mRootView = createRootView(inflater,container,savedInstanceState);
|
if(isBinding()){
|
mBinding = DataBindingUtil.bind(mRootView);
|
}
|
initViewModel();
|
return mRootView;
|
|
}
|
|
@Override
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
super.onViewCreated(view, savedInstanceState);
|
initView(savedInstanceState);
|
initData(savedInstanceState);
|
}
|
|
@Override
|
public void onActivityCreated(Bundle savedInstanceState) {
|
super.onActivityCreated(savedInstanceState);
|
initWindow(getDialog().getWindow());
|
}
|
|
protected void initDialog(Dialog dialog){
|
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
dialog.setCanceledOnTouchOutside(false);
|
}
|
|
protected void initWindow(Window window){
|
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
window.getAttributes().windowAnimations = R.style.mvvmframe_dialog_animation;
|
setWindow(window, DEFAULT_WIDTH_RATIO);
|
}
|
|
/**
|
* 创建 {@link #mRootView}
|
* @param inflater
|
* @param container
|
* @param savedInstanceState
|
* @return
|
*/
|
protected View createRootView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){
|
return inflater.inflate(getLayoutId(),container,false);
|
}
|
|
/**
|
* 获取rootView
|
* @return {@link #mRootView}
|
*/
|
protected View getRootView(){
|
return mRootView;
|
}
|
|
public <T extends View> T findViewById(@IdRes int id) {
|
return getRootView().findViewById(id);
|
}
|
|
/**
|
* 初始化 {@link #mViewModel}
|
*/
|
private void initViewModel(){
|
mViewModel = createViewModel();
|
if(mViewModel != null){
|
getLifecycle().addObserver(mViewModel);
|
registerLoadingEvent();
|
}
|
}
|
|
private Class<VM> getVMClass(){
|
Class cls = getClass();
|
Class<VM> vmClass = null;
|
while (vmClass == null && cls!= null){
|
vmClass = getVMClass(cls);
|
cls = cls.getSuperclass();
|
}
|
if(vmClass == null){
|
vmClass = (Class<VM>) BaseViewModel.class;
|
}
|
return vmClass;
|
}
|
|
private Class getVMClass(Class cls){
|
Type type = cls.getGenericSuperclass();
|
if(type instanceof ParameterizedType){
|
Type[] types = ((ParameterizedType)type).getActualTypeArguments();
|
for(Type t : types){
|
if(t instanceof Class){
|
Class vmClass = (Class)t;
|
if(BaseViewModel.class.isAssignableFrom(vmClass)){
|
return vmClass;
|
}
|
}else if(t instanceof ParameterizedType){
|
Type rawType = ((ParameterizedType)t).getRawType();
|
if(rawType instanceof Class){
|
Class vmClass = (Class)rawType;
|
if(BaseViewModel.class.isAssignableFrom(vmClass)){
|
return vmClass;
|
}
|
}
|
}
|
}
|
}
|
|
return null;
|
}
|
|
@Override
|
public void onDestroy() {
|
super.onDestroy();
|
|
if(mViewModel!=null){
|
getLifecycle().removeObserver(mViewModel);
|
}
|
mViewModel = null;
|
|
if(mBinding!=null){
|
mBinding.unbind();
|
}
|
}
|
|
/**
|
* 注册状态监听
|
*/
|
protected void registerLoadingEvent(){
|
mViewModel.getLoadingEvent().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
|
@Override
|
public void onChanged(@Nullable Boolean isLoading) {
|
if(isLoading){
|
showLoading();
|
}else{
|
hideLoading();
|
}
|
}
|
});
|
}
|
|
@Override
|
public void showLoading() {
|
showProgressDialog();
|
}
|
|
@Override
|
public void hideLoading() {
|
dismissProgressDialog();
|
}
|
|
/**
|
* 注册消息事件
|
*/
|
protected void registerMessageEvent(@NonNull MessageEvent.MessageObserver observer){
|
mViewModel.getMessageEvent().observe(getViewLifecycleOwner(),observer);
|
}
|
|
/**
|
* 注册单个消息事件,消息对象:{@link Message}
|
* @param observer
|
*/
|
protected void registerSingleLiveEvent(@NonNull Observer<Message> observer){
|
mViewModel.getSingleLiveEvent().observe(getViewLifecycleOwner(),observer);
|
}
|
|
/**
|
* 注册状态事件
|
* @param observer
|
*/
|
protected void registerStatusEvent(@NonNull StatusEvent.StatusObserver observer){
|
mViewModel.getStatusEvent().observe(getViewLifecycleOwner(),observer);
|
}
|
|
/**
|
* 是否使用DataBinding
|
* @return 默认为true 表示使用。如果为false,则不会初始化 {@link #mBinding}。
|
*/
|
@Override
|
public boolean isBinding(){
|
return true;
|
}
|
|
/**
|
* 创建ViewModel
|
* @return 默认为null,为null时,{@link #mViewModel}会默认根据当前Activity泛型 {@link VM}获得ViewModel
|
*/
|
@Override
|
public VM createViewModel(){
|
return obtainViewModel(getVMClass());
|
}
|
|
/**
|
* 获取 ViewModel
|
* @return {@link #mViewModel}
|
*/
|
public VM getVM(){
|
return mViewModel;
|
}
|
|
/**
|
* 获取 ViewDataBinding
|
* @return {@link #mBinding}
|
*/
|
public VDB getDB(){
|
return mBinding;
|
}
|
|
/**
|
* 通过 {@link #createViewModelProvider(ViewModelStoreOwner)}获得 ViewModel
|
* @param modelClass
|
* @param <T>
|
* @return
|
*/
|
public <T extends ViewModel> T obtainViewModel(@NonNull Class<T> modelClass){
|
return createViewModelProvider(this).get(modelClass);
|
}
|
|
/**
|
* @deprecated 请使用 {@link #obtainViewModel(Class)}
|
* @param modelClass
|
* @param <T>
|
* @return
|
*/
|
@Deprecated
|
public <T extends ViewModel> T getVM(@NonNull Class<T> modelClass){
|
return obtainViewModel(modelClass);
|
}
|
|
/**
|
* 创建 {@link ViewModelProvider}
|
* @param owner
|
* @return
|
*/
|
private ViewModelProvider createViewModelProvider(@NonNull ViewModelStoreOwner owner){
|
return new ViewModelProvider(owner);
|
}
|
|
//---------------------------------------
|
protected void finish(){
|
getActivity().finish();
|
}
|
|
protected Intent newIntent(Class<?> cls){
|
return new Intent(getContext(),cls);
|
}
|
|
protected Intent newIntent(Class<?> cls, int flags){
|
Intent intent = newIntent(cls);
|
intent.addFlags(flags);
|
return intent;
|
}
|
|
protected void startActivity(Class<?> cls){
|
startActivity(newIntent(cls));
|
}
|
|
protected void startActivity(Class<?> cls, int flags){
|
startActivity(newIntent(cls,flags));
|
}
|
|
protected void startActivity(Class<?> cls, @Nullable ActivityOptionsCompat optionsCompat){
|
startActivity(newIntent(cls),optionsCompat);
|
}
|
|
protected void startActivity(Class<?> cls, int flags, @Nullable ActivityOptionsCompat optionsCompat){
|
startActivity(newIntent(cls,flags),optionsCompat);
|
}
|
|
protected void startActivity(Intent intent, @Nullable ActivityOptionsCompat optionsCompat){
|
if(optionsCompat != null){
|
startActivity(intent,optionsCompat.toBundle());
|
}else{
|
startActivity(intent);
|
}
|
}
|
|
protected void startActivityFinish(Class<?> cls){
|
startActivity(cls);
|
finish();
|
}
|
|
protected void startActivityFinish(Class<?> cls, int flags){
|
startActivity(cls,flags);
|
finish();
|
}
|
|
protected void startActivityFinish(Class<?> cls, @Nullable ActivityOptionsCompat optionsCompat){
|
startActivity(cls,optionsCompat);
|
finish();
|
}
|
|
protected void startActivityFinish(Class<?> cls, int flags, @Nullable ActivityOptionsCompat optionsCompat){
|
startActivity(newIntent(cls,flags),optionsCompat);
|
}
|
|
protected void startActivityFinish(Intent intent, @Nullable ActivityOptionsCompat optionsCompat){
|
startActivity(intent,optionsCompat);
|
}
|
|
protected void startActivityForResult(Class<?> cls, int requestCode){
|
startActivityForResult(newIntent(cls),requestCode);
|
}
|
|
protected void startActivityForResult(Class<?> cls, int requestCode, @Nullable ActivityOptionsCompat optionsCompat){
|
Intent intent = newIntent(cls);
|
if(optionsCompat != null){
|
startActivityForResult(intent,requestCode,optionsCompat.toBundle());
|
}else{
|
startActivityForResult(intent,requestCode);
|
}
|
}
|
|
//---------------------------------------
|
|
protected View inflate(@LayoutRes int id){
|
return inflate(id,null);
|
}
|
|
protected View inflate(@LayoutRes int id, @Nullable ViewGroup root){
|
return LayoutInflater.from(getContext()).inflate(id,root);
|
}
|
|
protected View inflate(@LayoutRes int id, @Nullable ViewGroup root, boolean attachToRoot){
|
return LayoutInflater.from(getContext()).inflate(id,root,attachToRoot);
|
}
|
|
//---------------------------------------
|
|
protected void showDialogFragment(DialogFragment dialogFragment){
|
String tag = dialogFragment.getTag() !=null ? dialogFragment.getTag() : dialogFragment.getClass().getSimpleName();
|
showDialogFragment(dialogFragment,tag);
|
}
|
|
protected void showDialogFragment(DialogFragment dialogFragment, String tag) {
|
dialogFragment.show(getFragmentManager(),tag);
|
}
|
|
protected void showDialogFragment(DialogFragment dialogFragment, FragmentManager fragmentManager, String tag) {
|
dialogFragment.show(fragmentManager,tag);
|
}
|
|
protected Dialog getProgressDialog(){
|
return this.mProgressDialog;
|
}
|
|
protected void dismissDialog(Dialog dialog){
|
if(dialog != null && dialog.isShowing()){
|
dialog.dismiss();
|
}
|
}
|
|
protected void dismissPopupWindow(PopupWindow popupWindow){
|
if(popupWindow!=null && popupWindow.isShowing()){
|
popupWindow.dismiss();
|
}
|
}
|
|
protected void dismissProgressDialog(){
|
dismissDialog(mProgressDialog);
|
}
|
|
protected void showProgressDialog(){
|
showProgressDialog(false);
|
}
|
|
protected void showProgressDialog(boolean isCancel){
|
showProgressDialog(R.layout.mvvmframe_progress_dialog,isCancel);
|
}
|
|
protected void showProgressDialog(@LayoutRes int resId){
|
showProgressDialog(resId,false);
|
}
|
|
protected void showProgressDialog(@LayoutRes int resId,boolean isCancel){
|
showProgressDialog(inflate(resId),isCancel);
|
}
|
|
protected void showProgressDialog(View v){
|
showProgressDialog(v,false);
|
}
|
|
protected void showProgressDialog(View v, boolean isCancel){
|
dismissProgressDialog();
|
mProgressDialog = BaseProgressDialog.newInstance(getContext());
|
mProgressDialog.setContentView(v);
|
mProgressDialog.setCanceledOnTouchOutside(isCancel);
|
mProgressDialog.show();
|
}
|
|
protected void setDialogWindow(Dialog dialog, float widthRatio){
|
setWindow(dialog.getWindow(),widthRatio);
|
}
|
|
protected void setWindow(Window window, float widthRatio){
|
WindowManager.LayoutParams lp = window.getAttributes();
|
lp.width = (int)(getWidthPixels() * widthRatio);
|
window.setAttributes(lp);
|
}
|
|
//---------------------------------------
|
|
protected DisplayMetrics getDisplayMetrics(){
|
return getResources().getDisplayMetrics();
|
}
|
|
protected int getWidthPixels(){
|
return getDisplayMetrics().widthPixels;
|
}
|
|
protected int getHeightPixels(){
|
return getDisplayMetrics().heightPixels;
|
}
|
|
}
|