| | |
| | | package com.android.app_base.base.view; |
| | | |
| | | |
| | | import android.app.Activity; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | import android.os.Bundle; |
| | | import android.text.TextUtils; |
| | | import android.view.View; |
| | | import android.view.ViewGroup; |
| | | import android.view.Window; |
| | | import android.view.inputmethod.InputMethodManager; |
| | | |
| | | import androidx.annotation.NonNull; |
| | | import androidx.annotation.Nullable; |
| | | import androidx.appcompat.app.AppCompatActivity; |
| | | import androidx.databinding.DataBindingUtil; |
| | | import androidx.databinding.ViewDataBinding; |
| | | import androidx.drawerlayout.widget.DrawerLayout; |
| | | import androidx.lifecycle.Observer; |
| | | import androidx.lifecycle.ViewModelProvider; |
| | | import androidx.lifecycle.ViewModelStoreOwner; |
| | | |
| | | import com.android.app_base.action.TitleBarAction; |
| | | import com.android.app_base.base.action.ClickAction; |
| | | import com.android.app_base.base.viewmodel.BaseViewModel; |
| | | import com.android.app_base.base.StateViewEnum; |
| | | import com.android.app_base.base.viewmodel.SimpleViewModel; |
| | | import com.blankj.utilcode.util.ToastUtils; |
| | | import com.gyf.immersionbar.ImmersionBar; |
| | | import com.hjq.bar.TitleBar; |
| | | |
| | | import java.lang.reflect.ParameterizedType; |
| | | import java.lang.reflect.Type; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * Activity基类,所有的 Activity 都要继承此类 |
| | | */ |
| | | public abstract class BaseActivity<V extends ViewDataBinding,VM extends BaseViewModel> extends AppCompatActivity { |
| | | protected V binding; |
| | | public abstract class BaseActivity<VDB extends ViewDataBinding,VM extends BaseViewModel> extends AppCompatActivity implements TitleBarAction, ClickAction { |
| | | protected VDB binding; |
| | | protected VM viewModel; |
| | | private int viewModelId; |
| | | |
| | | /** |
| | | * 标题栏对象 |
| | | */ |
| | | private TitleBar mTitleBar; |
| | | /** |
| | | * 状态栏沉浸 |
| | | */ |
| | | private ImmersionBar mImmersionBar; |
| | | |
| | | @Override |
| | | protected void onCreate(@Nullable Bundle savedInstanceState) { |
| | | super.onCreate(savedInstanceState); |
| | | //绑定 ViewDataBinding 和 ViewModel |
| | | initViewDataBindingAndViewModel(); |
| | | //初始化状态视图 |
| | | initStateView(); |
| | | //Layout初始化 |
| | | initLayout(); |
| | | //页面参数初始化方法 |
| | | initParam(); |
| | | //页面view初始化方法 |
| | | initView(); |
| | | //页面数据初始化方法 |
| | | initData(); |
| | | //页面事件监听的方法,用于ViewModel层转到View层的事件注册 |
| | | initLiveDataObserve(); |
| | | //页面数据初始化方法 |
| | | initData(); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected void onDestroy() { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化布局 |
| | | */ |
| | | protected void initLayout(){ |
| | | //绑定 ViewDataBinding 和 ViewModel |
| | | initViewDataBindingAndViewModel(); |
| | | //初始化状态视图 |
| | | initStateView(); |
| | | //初始化沉浸式状态栏和 titleBar |
| | | initStatusBar(); |
| | | initSoftKeyboard(); |
| | | } |
| | | |
| | | /** |
| | | * ViewDataBinding和 ViewModel的获取及相关绑定 |
| | | */ |
| | | private void initViewDataBindingAndViewModel() { |
| | | binding = DataBindingUtil.setContentView(this, getLayoutId()); |
| | | protected void initViewDataBindingAndViewModel() { |
| | | if (getLayoutId() > 0) { |
| | | binding = initViewBinding(); |
| | | } |
| | | viewModelId = getVariableId(); |
| | | viewModel = initViewModel(); |
| | | //关联ViewModel |
| | | binding.setVariable(viewModelId, viewModel); |
| | | //支持LiveData绑定xml,数据改变,UI自动会更新 |
| | | binding.setLifecycleOwner(this); |
| | | //让ViewModel拥有View的生命周期感应 |
| | | getLifecycle().addObserver(viewModel); |
| | | |
| | | if (binding != null){ |
| | | //关联ViewModel |
| | | if (viewModelId > 0){ |
| | | binding.setVariable(viewModelId, viewModel); |
| | | } |
| | | //支持LiveData绑定xml,数据改变,UI自动会更新 |
| | | binding.setLifecycleOwner(this); |
| | | //让ViewModel拥有View的生命周期感应 |
| | | getLifecycle().addObserver(viewModel); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化ViewBinding |
| | | */ |
| | | protected VDB initViewBinding() { |
| | | return DataBindingUtil.setContentView(this, getLayoutId()); |
| | | } |
| | | /** |
| | | * 初始化ViewModel |
| | | * @return 返回一个ViewModel |
| | | */ |
| | | private VM initViewModel() { |
| | | protected VM initViewModel() { |
| | | Class<VM> vmClass; |
| | | Type type = getClass().getGenericSuperclass(); |
| | | if (type instanceof ParameterizedType){ |
| | | vmClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[1]; |
| | | } else { |
| | | //如果没有指定泛型参数,则默认使用BaseViewModel |
| | | vmClass = (Class<VM>) BaseViewModel.class; |
| | | //如果没有指定泛型参数,则默认使用SimpleViewModel |
| | | vmClass = (Class<VM>) SimpleViewModel.class; |
| | | } |
| | | return new ViewModelProvider(this, (ViewModelProvider.Factory) ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(vmClass); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 对状态视图liveData进行观察监听 |
| | | */ |
| | | private void initStateView() { |
| | | protected void initStateView() { |
| | | viewModel.getStateViewLiveData().observe(this, new Observer<StateViewEnum>() { |
| | | @Override |
| | | public void onChanged(StateViewEnum stateViewEnum) { |
| | |
| | | break; |
| | | case DATA_LOADING: |
| | | dataLoading(); |
| | | break; |
| | | case DATA_FINISH: |
| | | dataFinish(); |
| | | break; |
| | | case DATA_ERROR: |
| | | dataError(); |
| | |
| | | } |
| | | } |
| | | }); |
| | | viewModel.getMessageLivaData().observe(this, new Observer<String>() { |
| | | @Override |
| | | public void onChanged(String message) { |
| | | if (!TextUtils.isEmpty(message)){ |
| | | ToastUtils.showShort(message); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 缺省页等状态视图的更新 |
| | | * 有需求的,在子类选择重写 |
| | |
| | | } |
| | | protected void dataLoading() { |
| | | } |
| | | protected void dataFinish() { |
| | | } |
| | | protected void dataError() { |
| | | } |
| | | protected void dataNull() { |
| | |
| | | protected void netError() { |
| | | } |
| | | protected void hide() { |
| | | } |
| | | |
| | | /** |
| | | * 初始化沉浸式状态栏 |
| | | */ |
| | | protected void initStatusBar(){ |
| | | if (getTitleBar() != null) { |
| | | getTitleBar().setOnTitleBarListener(this); |
| | | } |
| | | if (isStatusBarImmersionEnabled()) { |
| | | getImmersionBarConfig().init(); |
| | | // 设置标题栏沉浸() |
| | | if (getTitleBar() != null) { |
| | | ImmersionBar.setTitleBar(this, getTitleBar()); |
| | | } |
| | | } |
| | | } |
| | | /** |
| | | * 是否使用沉浸式状态栏,可以子类重写指定 |
| | | */ |
| | | protected boolean isStatusBarImmersionEnabled() { |
| | | return true; |
| | | } |
| | | /** |
| | | * 获取状态栏沉浸的配置对象 |
| | | */ |
| | | @NonNull |
| | | public ImmersionBar getImmersionBarConfig() { |
| | | if (mImmersionBar == null) { |
| | | mImmersionBar = createStatusBarConfig(); |
| | | } |
| | | return mImmersionBar; |
| | | } |
| | | /** |
| | | * 创建状态栏沉浸的配置对象 |
| | | */ |
| | | @NonNull |
| | | protected ImmersionBar createStatusBarConfig() { |
| | | return ImmersionBar.with(this) |
| | | // 默认状态栏字体颜色为黑色 |
| | | .statusBarDarkFont(isStatusBarDarkFont(),0.2f);//不写默认为亮色 |
| | | } |
| | | /** |
| | | * 状态栏字体深色模式 |
| | | */ |
| | | protected boolean isStatusBarDarkFont() { |
| | | return true; |
| | | } |
| | | @Override |
| | | @Nullable |
| | | public TitleBar getTitleBar() { |
| | | if (mTitleBar == null) { |
| | | mTitleBar = obtainTitleBar(findViewById(Window.ID_ANDROID_CONTENT)); |
| | | } |
| | | return mTitleBar; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public abstract void initLiveDataObserve(); |
| | | |
| | | @Override |
| | | public void finish() { |
| | | hideSoftKeyboard(); |
| | | super.finish(); |
| | | } |
| | | |
| | | /** |
| | | * 隐藏软键盘 |
| | | */ |
| | | protected void hideSoftKeyboard() { |
| | | // 隐藏软键盘,避免软键盘引发的内存泄露 |
| | | View view = getCurrentFocus(); |
| | | if (view != null) { |
| | | InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); |
| | | if (manager != null && manager.isActive(view)) { |
| | | manager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); |
| | | view.clearFocus(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 初始化软键盘 |
| | | */ |
| | | protected void initSoftKeyboard() { |
| | | // 点击外部隐藏软键盘,提升用户体验 |
| | | getContentView().setOnClickListener(v -> hideSoftKeyboard()); |
| | | } |
| | | |
| | | public ViewGroup getContentView() { |
| | | return findViewById(Window.ID_ANDROID_CONTENT); |
| | | } |
| | | |
| | | public Activity getSelfActivity() { |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * 如果当前的 Activity(singleTop 启动模式) 被复用时会回调 |
| | | */ |
| | | @Override |
| | | protected void onNewIntent(Intent intent) { |
| | | super.onNewIntent(intent); |
| | | // 设置为当前的 Intent,避免 Activity 被杀死后重启 Intent 还是最原先的那个 |
| | | setIntent(intent); |
| | | } |
| | | |
| | | } |