android项目构建之公共父类MyApplication,BaseActivity,BaseFragment

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lijizhi19950123/article/details/79337368

自从开始参加了工作之后,貌似已经很长时间没有写博客了,其中最主要的原因还是因为前些阵子要赶项目经常加班疏忽了,还好现在正值春节期间,我就可以好好整理一下自己的知识体系了。

什么是Application

 Application和Activity,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建,如果需要创建自己 的Application,也很简单创建一个类继承 Application并在manifest的application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。具体代码如下

public class MyApplication extends Application {

    private static MyApplication instances;
    private int appCount = 0;
    private boolean showForceLogoutDialog = false;
    private boolean updateLocalData = false;
    private String message = "";

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instances = this;
        Utils.init(getApplicationContext());
        if (BuildConfig.DEBUG) {
            /*测试配置*/
            Logger.addLogAdapter(new AndroidLogAdapter());
        } else {
            /*发布配置*/
//            Bugly.setUserId(getApplicationContext(),
//                    String.valueOf(SignInUtils.getUserBean(getApplicationContext()).getId()));
        }

        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

            }

            @Override
            public void onActivityStarted(Activity activity) {
                appCount++;
            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {
                appCount--;
            }

            @Override
            public void onActivitySaveInstanceState(Activity  activity, Bundle outState) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });
    }


    public static MyApplication getInstances() {
        return instances;
    }

    public int getAppCount() {
        return appCount;
    }

    public boolean isShowForceLogoutDialog() {
        return showForceLogoutDialog;
    }

    public void setShowForceLogoutDialog(boolean showForceLogoutDialog) {
        this.showForceLogoutDialog = showForceLogoutDialog;
    }

    public boolean isUpdateLocalData() {
        return updateLocalData;
    }

    public void setUpdateLocalData(boolean updateLocalData) {
        this.updateLocalData = updateLocalData;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
什么是BaseActivity

BaseActivity主要作用是要作为Activity的公共父类存在,将那些公有的第三方初始化的工作放在里面避免重复代码,范例代码如下所示:

public abstract class BaseActivity extends RxAppCompatActivity {
    //设置兼容5.0以下使用矢量图
    static {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
        }
    }
    //声明全局加载dialog
    public Dialog loadingDialog;
    //默认不是最后一页
    public boolean lastPage = false;
    //默认为第一页
    public int page = BaseContants.DEFAULT_FIRST_PAGE;

    //EventBus接收信息并处理信息
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(ServerMsgEvent serverMsgEvent) {
        //如果APP在前台运行,弹出toast
        if (!AppUtils.isBackground(this)) {
            ToastUtils.showShortToast(serverMsgEvent.getDesc());
        }
        //如果登录信息失效且本地登录信息还在,调用强制退出逻辑
        if (serverMsgEvent.getResult() == HttpResult.SERVER_RESULT_CODE_TOKEN_INVALID) {
            if (!TextUtils.isEmpty(SignInUtils.getTokenId(this))) {
                SignInUtils.forceLogout(this, serverMsgEvent.getDesc());
            }
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        preInit();
        super.setContentView(getLayoutId());
        ButterKnife.bind(this);
        setStatusBar();
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        //注册EventBus
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }

        initStatusBar();
        initToolbar();
        initProgressDialog();
        initView();
        initData();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //从后台切换到前台时,检查是否显示强制登出对话框,适用于透传推送踢出登录场景
        if (MyApplication.getInstances().isShowForceLogoutDialog()) {
            MyApplication.getInstances().setShowForceLogoutDialog(false);
            Bundle bundle = new Bundle();
            bundle.putString(BaseContants.KEY_NOTIFICATION_MESSAGE, MyApplication.getInstances().getMessage());
            skipToActivity(DialogActivity.class, bundle);
        }

       从后台切换到前台时,检查是否更新本地筛选数据,保证及时更新筛选数据
   if (MyApplication.getInstances().isUpdateLocalData()) {
         MyApplication.getInstances().setUpdateLocalData(false);
           Map<String, Object> map = new HashMap<>();
            map.put(BaseContants.PARAM_CHECK_UPDATE_TYPE, BaseContants.CHECK_UPDATE_TYPE_ANDROID);
           addDisposable(RetrofitManager.getAPIService()
                   .findDataVersion(map)
                    .compose(RxUtil.<HttpResult<FindDataVersion>>applySchedulers())
                    .compose(this.<HttpResult<FindDataVersion>>bindToLifecycle())
                    .subscribeWith(new BaseSubscriber<FindDataVersion>() {
                        @Override
                        public void handlerSuccess(final FindDataVersion findDataVersion) {
                            new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    DataVersionUtils.updateLocalData(BaseActivity.this, findDataVersion);
                               }
                            }).start();
                        }
                    }));

            checkUpdate();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (!AppUtils.isForeground()) {
            //切换到后台时,设置更新筛选数据开关为打开,重新打开APP时更新数据
            MyApplication.getInstances().setUpdateLocalData(true);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        String key = getPackageName() + BaseContants.SYMBOL_DOT + getClass().getSimpleName();
        RetrofitManager.remove(key);
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    // 获取布局资源
    protected abstract int getLayoutId();

    // 初始化界面
    protected abstract void initView();

    // 初始化数据
    protected abstract void initData();

    //检查更新状态
    public void checkUpdate() {

    }

    //预初始化
    public void preInit() {
        //android版本大于4.4,设置沉浸式状态栏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    //设置状态栏
    protected void setStatusBar() {
        StatusBarUtil.setColor(this, getResources().getColor(R.color.colorPrimary));
    }

    //初始化状态栏
    private void initStatusBar() {
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        ViewGroup decorViewGroup = (ViewGroup) window.getDecorView();
        View statusBarView = new View(window.getContext());
        int statusBarHeight = getStatusBarHeight(window.getContext());
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, statusBarHeight);
        params.gravity = Gravity.TOP;
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
        decorViewGroup.addView(statusBarView);

        ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
        View mChildView = mContentView.getChildAt(0);
        if (mChildView != null) {
            //注意不是设置 ContentView 的 FitsSystemWindows, 而是设置 ContentView 的第一个子 View . 预留出系统 View 的空间.
            mChildView.setFitsSystemWindows(true);
        }
    }

    //获取状态栏的高度
    private static int getStatusBarHeight(Context context) {
        int statusBarHeight = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }

    //初始化ToolBar
    public void initToolbar() {
        Toolbar toolbar = findViewById(R.id.toolbar);
        if (toolbar != null) {
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    finish();
                }
            });
        }
        setSupportActionBar(toolbar);
        if (getSupportActionBar() != null) {
            // 给左上角图标的左边加上一个返回的图标
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }
    }

    //初始化化进度对话框
    public void initProgressDialog() {
        View v =  LayoutInflater.from(this).inflate(R.layout.loading_progress, null);
        RelativeLayout layout = v.findViewById(R.id.dialog_loading_view);
        loadingDialog = new Dialog(this, R.style.LoadingDialogStyle);
        loadingDialog.setCancelable(true);
        loadingDialog.setCanceledOnTouchOutside(false);
        loadingDialog.setContentView(layout, new RelativeLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));

        Window window = loadingDialog.getWindow();
        if (window != null) {
            WindowManager.LayoutParams lp = window.getAttributes();
            lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
            window.setGravity(Gravity.CENTER);
            window.setAttributes(lp);
            window.setWindowAnimations(R.style.PopWindowAnimStyle);
        }
    }

    //被观察者与观察者之间添加订阅关系
    protected void addDisposable(Disposable disposable) {
        String key = getPackageName() + BaseContants.SYMBOL_DOT + getClass().getSimpleName();
        RetrofitManager.add(key, disposable);
    }

    //跳转到任意界面,并且通过bundle携带数据
    protected void skipToActivity(Class<?> clazz, Bundle bundle) {
        Intent intent = new Intent(this, clazz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    //跳转到任意界面结束当前界面,并且通过bundle携带数据
    protected void skipToActivityAndFinish(Class<?> clazz, Bundle bundle) {
        Intent intent = new Intent(this, clazz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
        finish();
    }

    //跳转到任意界面,通过bundle传递数据,并且通过request返回数据给当前界面
    protected void skipToActivityForResult(Class<?> clazz, Bundle bundle, int requestCode) {
        Intent intent = new Intent(this, clazz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    //关闭当前界面
    protected void closeActivity(Bundle bundle) {
        if (bundle != null) {
            Intent intent = new Intent();
            intent.putExtras(bundle);
            setResult(RESULT_OK, intent);
        }
        finish();
    }
}
什么是BaseFragment

BaseFragment的作用大体是和BaseActivity一致,也是作为Fragment的公共父类存在,在其中主要是对Fragment进行初始化以及对fragment进行懒加载,范例代码如下所示

public abstract class BaseFragment extends RxFragment {
    Unbinder unbinder;
    //声明一个view
    protected View rootView;
    //记录位置标签
    String mPositionTag = "";
    //记录开启进度条的情况,只能开一个
    private int count;
    //当前Fragment是否处于可见状态标志,防止因ViewPager的缓存机制而导致回调函数的触发
    private boolean isFragmentVisible;
    //是否是第一次开启网络加载
    public  boolean isFirst;
    //刷新默认为第一页
    public int page = BaseContants.DEFAULT_FIRST_PAGE;
    //默认不是最后一页
    public boolean lastPage = false;

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(SignOrBindEvent signOrBindEvent) {
        initData();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if(rootView!=null) {
            rootView= inflater.inflate(getLayoutId(), container, false);
        }
        unbinder = ButterKnife.bind(this, rootView);

        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
        initView();
        initData();
        if(isFragmentVisible&&!isFirst){
            onFragmentVisibleChange(true);
        }
        return rootView;
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();

        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }

        String key = Utils.getContext().getApplicationContext().getPackageName() + BaseContants.SYMBOL_DOT + getClass().getSimpleName() + mPositionTag;
        RetrofitManager.remove(key);
    }

    protected abstract int getLayoutId();

    protected abstract void initView();

    protected abstract void initData();

    protected void addDisposable(Disposable disposable) {
        String key = Utils.getContext().getPackageName() + BaseContants.SYMBOL_DOT + this.getClass().getSimpleName();
        RetrofitManager.add(key, disposable);
    }

    protected void addDisposable(Disposable disposable, String positionTag) {
        String key = "";
        mPositionTag = positionTag;
        key = Utils.getContext().getApplicationContext().getPackageName() + BaseContants.SYMBOL_DOT + getClass().getSimpleName() + positionTag;
        RetrofitManager.add(key, disposable);
    }

    /**
     * 跳转到指定的Activity
     */
    protected void skipToActivity(Class<?> clazz, Bundle bundle) {
        Intent intent = new Intent(getActivity(), clazz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    /**
     * 跳转到指定的Activity并结束当前Activity
     */
    protected void skipToActivityAndFinish(Class<?> clazz, Bundle bundle) {
        Intent intent = new Intent(getActivity(), clazz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
        if (getActivity() != null) {
            getActivity().finish();
        }
    }

    /**
     * 带返回的跳转到指定Activity
     */
    protected void skipToActivityForResult(Class<?> clazz, Bundle bundle, int requestCode) {
        Intent intent = new Intent(getActivity(), clazz);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    /**
     * 关闭Activity
     */
    protected void closeActivity(Bundle bundle) {
        Intent intent = new Intent();
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        if (getActivity()!=null){
            getActivity().setResult(Activity.RESULT_OK, intent);
            getActivity().finish();
        }
    }

    /**
     * 设置Fragment是否可见
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser){
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser){
            isFragmentVisible=true;
        }
        if(rootView==null){
            return;
        }
        //可见,并且没有加载过
        if(!isFirst&&isFragmentVisible){
            onFragmentVisibleChange(true);
        }
        //由可见-->不可见 已经加载过
        if(isFragmentVisible){
            onFragmentVisibleChange(false);
            isFragmentVisible = false;
        }
    }

    /**
     * 当前fragment可见状态发生变化时会回调该方法
     * 如果当前Fragment的是第一次加载,等待onCreateView后才会回调该方法,其他情况回调时机跟{@link #setUserVisibleHint(boolean)一致
     * 在该回调方法中你可以做一些加载数据的操作,甚至是控件的操作
     * @param isVisible true 不可见 -> 可见 ,false 可见 -> 不可见
     */

     protected void onFragmentVisibleChange(boolean isVisible){

     }
}

总结

当然了,我在这里也只是做了一个示范,我相信一定会有更好的写法,欢迎志同道合的朋友提出宝贵意见,共同学习进步!

猜你喜欢

转载自blog.csdn.net/lijizhi19950123/article/details/79337368