package com.doumee.lib_coremodel.base; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Message; import android.text.TextUtils; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.view.WindowManager; import android.webkit.WebView; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StyleRes; import androidx.appcompat.app.AppCompatActivity; 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.ViewModelProviders; import androidx.lifecycle.ViewModelStoreOwner; import com.gyf.immersionbar.BarHide; import com.gyf.immersionbar.ImmersionBar; import com.doumee.lib_coremodel.R; import com.doumee.lib_coremodel.base.livedata.ActionEvent; import com.doumee.lib_coremodel.base.livedata.MessageEvent; import com.doumee.lib_coremodel.base.livedata.StatusEvent; import com.doumee.lib_coremodel.bean.event.ActionEventData; import com.doumee.lib_coremodel.bean.event.TagEvent; import com.doumee.lib_coremodel.view.ToastView; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; /** * MVVMFrame 框架基于Google官方的 JetPack 构建,在使用MVVMFrame时,需遵循一些规范: * * 如果您继承使用了BaseActivity或其子类,你需要参照如下方式添加@AndroidEntryPoint注解 * * @example Activity * //------------------------- * @AndroidEntryPoint * public class YourActivity extends BaseActivity { * * } * //------------------------- * * @author Jenly */ public abstract class BaseActivity extends AppCompatActivity implements IView, BaseNavigator { protected String tag;//设置标志; /** * 请通过 {@link #getVM()}获取,后续版本 {@link #mViewModel}可能会私有化 */ private VM mViewModel; /** * 请通过 {@link #getDB()}获取,后续版本 {@link #mBinding}可能会私有化 */ private VDB mBinding; protected static final float DEFAULT_WIDTH_RATIO = 0.85f; private Dialog mDialog; public Context mContext; private Toast toast; protected BaseProgressDialog mProgressDialog; public boolean isNeedSetNomalBar=true; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initContentView(); if(!EventBus.getDefault().isRegistered(this)){ EventBus.getDefault().register(this); } mContext=this; initViewModel(); initView(savedInstanceState); initData(savedInstanceState); tag = getStringFormBundle("tag"); getVM().setTag(tag); } /** * 初始化ContentView,{@link #setContentView(int)} } */ protected void initContentView(){ if(isBinding()){ mBinding = DataBindingUtil.setContentView(this,getLayoutId()); }else{ setContentView(getLayoutId()); } } /** * 初始化 {@link #mViewModel} */ private void initViewModel(){ mViewModel = createViewModel(); if(mViewModel != null){ getLifecycle().addObserver(mViewModel); registerLoadingEvent(); } } protected void init(){ setImmersionBar(); normalConfig(); } public int getIntFormBundle(String key){ if(getIntent().getExtras()!=null){ return getIntent().getExtras().getInt(key); } return 0; } public String getStringFormBundle(String key){ if(getIntent().getExtras()!=null){ return getIntent().getExtras().getString(key); } return ""; } public void normalConfig(){ registerNormal(); getVM().setLifecycleOwner(this); setImmersionBarFullScreen(); } protected void setImmersionBar(){ //沉浸式状态栏 ImmersionBar.with(this).statusBarColor(R.color.transparent) .statusBarDarkFont(true) .fitsSystemWindows(true) .init(); } protected void setImmersionBarFullScreen(){ ImmersionBar.with(this) .statusBarColor(R.color.transparent) .hideBar(BarHide.FLAG_HIDE_STATUS_BAR) .statusBarDarkFont(true) .init(); } private Class getVMClass(){ Class cls = getClass(); Class vmClass = null; while (vmClass == null && cls!= null){ vmClass = getVMClass(cls); cls = cls.getSuperclass(); } if(vmClass == null){ vmClass = (Class) 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; } @Subscribe public void LogOutEvent(LogOutEvent event){ } @Override protected void onDestroy() { super.onDestroy(); if(EventBus.getDefault().isRegistered(this)){ EventBus.getDefault().unregister(this); } if(mViewModel != null){ getLifecycle().removeObserver(mViewModel); mViewModel = null; } if(toast!=null){ toast.cancel(); toast = null; } if(mBinding != null){ mBinding.unbind(); } } // 如果你的app可以横竖屏切换,并且适配4.4或者emui3手机请务必在onConfigurationChanged方法里添加这句话 @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); ImmersionBar.with(this).init(); } /** * 注册动作事件 */ protected void registerActionEvent(ActionEvent.ActionObserver observer){ mViewModel.getActionEvent().observe(this, observer); } /** * 注册状态加载事件 */ protected void registerLoadingEvent(){ mViewModel.getLoadingEvent().observe(this, new Observer() { @Override public void onChanged(@Nullable Boolean isLoading) { if(isLoading){ showLoading(); }else{ hideLoading(); } } }); } public void registerNormal(){ registerActionEvent(new ActionEvent.ActionObserver() { @Override public void onStatusChanged(ActionEventData data) { switch (data.getAction()){ case ActionEvent.Action.FINISH: finish(); break; case ActionEvent.Action.START_ACTIVITY: startActivity(data.getClassFromData(), data.getBundleFromData()); break; case ActionEvent.Action.TOAST: if(toast!=null){ toast.cancel(); } toast = ToastView.show(getApplicationContext(), (String) data.getData().get("toast")); //Toast.makeText(getContext(), data.getBundleFromData().getString("toast"), Toast.LENGTH_SHORT).show(); break; default: otherRegister(data); break; } } }); } protected void otherRegister(ActionEventData data){ switch (data.getAction()){ case ActionEvent.Action.DO: int type = (int) data.getData().get("type"); doRegister(type,data); break; default: break; } } protected void doRegister(int type,ActionEventData data){ } @Override public void showLoading() { showProgressDialog(); } @Override public void hideLoading() { dismissProgressDialog(); } /** * 注册消息事件 */ protected void registerMessageEvent(@NonNull MessageEvent.MessageObserver observer){ getVM().getMessageEvent().observe(this,observer); } /** * 注册单个消息事件,消息对象:{@link Message} * @param observer */ protected void registerSingleLiveEvent(@NonNull Observer observer){ getVM().getSingleLiveEvent().observe(this,observer); } /** * 注册状态事件 * @param observer */ protected void registerStatusEvent(@NonNull StatusEvent.StatusObserver observer){ getVM().getStatusEvent().observe(this,observer); } public Context getContext(){ return this; } /** * 是否使用DataBinding * @return 默认为true 表示使用。如果为false,则不会初始化 {@link #mBinding}。 */ @Override public boolean isBinding(){ return true; } /** * 创建ViewModel * @return {@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 * @return */ public T obtainViewModel(@NonNull Class modelClass){ return createViewModelProvider(this).get(modelClass); //return ViewModelProviders.of(this).get(modelClass); /*return new ViewModelProvider( this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()) ).get(modelClass);*/ } /** * @deprecated 请使用 {@link #obtainViewModel(Class)} * @param modelClass * @param * @return */ @Deprecated public T getVM(@NonNull Class modelClass){ return obtainViewModel(modelClass); } /** * 创建 {@link ViewModelProvider} * @param owner * @return */ private ViewModelProvider createViewModelProvider(@NonNull ViewModelStoreOwner owner){ return new ViewModelProvider(owner); } //--------------------------------------- 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)); } /** * 跳转页面 * * @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); } 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(getSupportFragmentManager(),tag); } protected void showDialogFragment(DialogFragment dialogFragment, FragmentManager fragmentManager, String tag) { dialogFragment.show(fragmentManager,tag); } private View.OnClickListener mOnDialogCancelClick = new View.OnClickListener() { @Override public void onClick(View v) { dismissDialog(); } }; protected Dialog getDialog(){ return this.mDialog; } protected Dialog getProgressDialog(){ return this.mProgressDialog; } protected View.OnClickListener getDialogCancelClick(){ return mOnDialogCancelClick; } protected void dismissDialog(){ dismissDialog(mDialog); } 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(true); } 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.getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE)); mProgressDialog.setContentView(v); mProgressDialog.setCanceledOnTouchOutside(isCancel); mProgressDialog.show(); /*try { mProgressDialog = ProgressDialog.show(this, "", ); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mProgressDialog.setCancelable(isCancel); mProgressDialog.show(); } catch (Exception e) { e.printStackTrace(); }*/ } protected void showDialog(View contentView){ showDialog(contentView,DEFAULT_WIDTH_RATIO); } protected void showDialog(View contentView, boolean isCancel){ showDialog(getContext(),contentView,R.style.mvvmframe_dialog,DEFAULT_WIDTH_RATIO,isCancel); } protected void showDialog(View contentView, float widthRatio){ showDialog(getContext(),contentView,widthRatio); } protected void showDialog(View contentView, float widthRatio, boolean isCancel){ showDialog(getContext(),contentView,R.style.mvvmframe_dialog,widthRatio,isCancel); } protected void showDialog(Context context, View contentView, float widthRatio){ showDialog(context,contentView, R.style.mvvmframe_dialog,widthRatio); } protected void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio){ showDialog(context,contentView,resId,widthRatio,true); } protected void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio, final boolean isCancel){ dismissDialog(); mDialog = new Dialog(context,resId); mDialog.setContentView(contentView); mDialog.setCanceledOnTouchOutside(false); mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK){ if(isCancel){ dismissDialog(); } return true; } return false; } }); setDialogWindow(mDialog,widthRatio); mDialog.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; } public void destroyWebView(WebView webView){ if (webView != null) { webView.clearCache(true); webView.clearHistory(); webView.removeAllViews(); // 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再 // destory() ViewParent parent = webView.getParent(); if (parent != null) { ((ViewGroup) parent).removeView(webView); } webView.stopLoading(); // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错 webView.getSettings().setJavaScriptEnabled(false); webView.clearHistory(); webView.clearView(); webView.removeAllViews(); try { webView.destroy(); } catch (Throwable ex) { } } } @Subscribe public void TagEvent(TagEvent event){ if(!TextUtils.isEmpty(tag)&&event.getTag().equals(tag)){ finish(); } } }