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();
}
}
}