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 <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
*/
|
|
public abstract class BaseActivity<VM extends BaseViewModel,VDB extends ViewDataBinding> extends AppCompatActivity implements IView<VM>, 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<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;
|
}
|
|
@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<Boolean>() {
|
@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<Message> 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 <T>
|
* @return
|
*/
|
public <T extends ViewModel> T obtainViewModel(@NonNull Class<T> 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 <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 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();
|
}
|
}
|
}
|