Android谈谈封装那些事--BaseActivity和BaseFragment(二)

简介: 版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/53889223 1.
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/53889223

1.前言

昨天谈了BaseActivity的封装,
Android谈谈封装那些事–BaseActivity和BaseFragment(一)
有很多小伙伴提了很多建议,比如:

  • 通用标题栏可以自定义View而不放在Base里面,代码更统一
  • BaseEventActivity里面应该留出开关保证不需要Bus的Activity使用
  • BaseStatusActivity里面就一个方法没必要新建一个
  • 还有一些小的细节

在这里感谢大家的建议了啊。我修改了一部分,后面会慢慢优化,最后在HLibrary里面贴出最优代码。还有那个BaseStatusActivity(沉浸栏)的也会继续优化的。接下来谈谈BaseFragment的封装,其实主要还是关于Fragment的懒加载问题。

2.Fragment相关知识点

  • 生命周期
  • Fragment的使用:静态、动态
  • Fragment应注意到的问题
  • ……

在这里就不详细介绍了,想了解的可以看我的这篇文章:

你真的会用Fragment了么?-Fragment解析

1.Fragment使用场景

我们可以看到市场的APP一般都是用底部Tab+fragment切换为整体架子的,或者通过viewpager作为容器嵌套fragment,再复杂点的就是fragment嵌套fragment,某书、某条等等都是这样;

2.遇到的问题

这样的话我们遇到的问题就是当fragment很多组合使用的时候,每个fragment里面都会加载数据或者执行动画等比较复杂的业务逻辑时,导致我们的APP进入时屏幕卡顿,性能很差,一点都不流畅。即便是我们在使用viewpager作为容器的时候设置预加载setOffscreenPageLimit()这个方法,其实你会发现根本不会起作用。
至于viewpager这个预加载方法为什么不行?我们可以看一下viewpager源码:


我们可以看到DEFAULT_OFFSCREEN_PAGES 这里就定义了默认值是1,如果你调用该方法传进来的值小于1是无效的,会被强行的拽回1。而且DEFAULT_OFFSCREEN_PAGES 这个值是private的,子类继承ViewPager也是不可见的。
网上有的说可以将viewpager的源码复制下来粘到自己的类里面将这个默认值改为0,这个目前还没试过,即使可以感觉也有些别扭,更何况我们使用场景也不一定需要viewpager呢

3.Fragment懒加载

这是靠Fragment里有一个setUserVisibleHint(boolean isVisibleToUser)的方法,我们可以在这个方法里做判断,当其True可见时(即切换到某一个具体Fragment)时才去加载数据,这样可以省流量。
具体怎么去操作呢?

  • 预加载初始化数据和组件等轻量操作
  • 切换tab到第一次可见时执行网络请求
  • 四种状态:第一次可见状态、可见状态、第一次不可见状态、不可见状态
  • 销毁时处理解注册、销毁广播等问题

3.BaseFragment封装

1.初始化xml文件

@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (getContentViewLayoutID() != 0) {
            return inflater.inflate(getContentViewLayoutID(), null);
        } else {
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    }

        protected abstract int getContentViewLayoutID();

2.注解绑定以及初始化组件

@Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ButterKnife.bind(this,view);
        initViewsAndEvents(view);
    }

    protected abstract void initViewsAndEvents(View view);

3.四种“见”的状态拆分

@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initPrepare();
    }

    private synchronized void initPrepare() {
        if (isPrepared) {
            onFirstUserVisible();
        } else {
            isPrepared = true;
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            if (isFirstVisible) {
                isFirstVisible = false;
                initPrepare();
            } else {
                onUserVisible();
            }
        } else {
            if (isFirstInvisible) {
                isFirstInvisible = false;
                onFirstUserInvisible();
            } else {
                onUserInvisible();
            }
        }
    }

    protected abstract void onFirstUserVisible();
    protected abstract void onUserVisible();
    private void onFirstUserInvisible() { }
    protected abstract void onUserInvisible();

4.最后解注册销毁等工作

@Override
    public void onDestroy() {
        DetoryViewAndThing();
        super.onDestroy();
    }

    protected abstract void DetoryViewAndThing();

5.跳转界面等方法

/**
     * 打开一个Activity 默认 不关闭当前activity
     */
    public void gotoActivity(Class<?> clz) {
        gotoActivity(clz, false, null);
    }

    public void gotoActivity(Class<?> clz, boolean isCloseCurrentActivity) {
        gotoActivity(clz, isCloseCurrentActivity, null);
    }

    public void gotoActivity(Class<?> clz, boolean isCloseCurrentActivity, Bundle ex) {
        Intent intent = new Intent(mActivity, clz);
        if (ex != null) intent.putExtras(ex);
        startActivity(intent);
        if (isCloseCurrentActivity) {
            mActivity.finish();
        }
    }

最后提一个小问题吧:就是说如果你没有用Fragment懒加载的话而是用的viewpager的预加载,如果你没有自己定义默认预加载个数的话,那么默认肯定是会提前加载的,加入你当前fragment相邻的fragment里面有动画或者视频播放的话,切换到当前fragment时候下个fragment里面的动画或者视频就已经开始执行了,注意一下。
到此我的base就告一段落了,很多不合理的地方,我接下来私下也会去听取小伙伴们的意见进行修改,然后最后在HLibrary里面贴出来的,非常感谢大家。

相关文章
|
6月前
|
Android开发 Python
Python封装ADB获取Android设备wifi地址的方法
Python封装ADB获取Android设备wifi地址的方法
150 0
|
Android开发
Android Http 请求封装及使用
Android Http 请求封装及使用
230 0
|
6月前
|
Android开发
Android 分享机顶盒项目的封装类《GridView》(二)(转)
Android 分享机顶盒项目的封装类《GridView》(二)(转)
48 2
|
3月前
|
Android开发 iOS开发
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
41 0
|
3月前
|
编解码 API 开发工具
Android平台轻量级RTSP服务模块二次封装版调用说明
本文介绍了Android平台上轻量级RTSP服务模块的二次封装实践,旨在简化开发流程,让开发者能更专注于业务逻辑。通过`LibPublisherWrapper`类提供的API,可在应用中轻松初始化RTSP服务、配置视频参数(如分辨率、编码类型)、启动与停止RTSP服务及流发布,并获取RTSP会话数量。此外,还展示了如何处理音频和视频数据的采集与推送。最后,文章提供了从启动服务到销毁资源的完整示例,帮助开发者快速集成实时流媒体功能。
|
5月前
|
Android开发 Kotlin
kotlin安卓开发【Jetpack Compose】:封装SnackBarUtil工具类方便使用
GPT-4o 是一个非常智能的模型,比当前的通义千问最新版本在能力上有显著提升。作者让GPT开发一段代码,功能为在 Kotlin 中使用 Jetpack Compose 框架封装一个 Snackbar 工具类,方便调用
|
6月前
|
XML Java Android开发
Android 分享机顶盒项目的封装类《GridView》(三)(转)
Android 分享机顶盒项目的封装类《GridView》(三)(转)
37 2
|
6月前
|
达摩院 安全 Java
80 PM撸代码之Android【武侠讲封装、继承、多态】
80 PM撸代码之Android【武侠讲封装、继承、多态】
47 0
|
API Android开发 Kotlin
安卓MVI架构真的来了?动手试着封装吧(三)下
安卓MVI架构真的来了?动手试着封装吧(三)
118 0
|
Android开发 开发者 Kotlin
安卓MVI架构真的来了?动手试着封装吧(三)上
安卓MVI架构真的来了?动手试着封装吧(三)
146 0