Android应用加载布局的时候有时候会出现重叠布局或者重叠组件--动态控制组件的显示或者隐藏

Android应用加载布局的时候有时候会出现重叠布局或者重叠组件的情况,比如一箱项目中开屏页之后可能会加载一个动画(VideoView),在有网络或者是后台返回广告(图片ImageView)的时候就需要进行动态控制组件的显示或者隐藏,首先我们需要明确一些参数设置效果:

基本概念

       1、在xml文件中对控件可进行配置

       2、在Java代码中进行设置

       可见:

               android:visibility="visible";

               Java代码:view.setVisibility(View.VISIBLE);

       不可见:

                  android:visibility="invisible";

                  Java代码:view.setVisibility(View.INVISIBLE);

        隐藏:

                android:visibility="gone";

                Java代码:view.setVisibility(View.GONE);

注意:invisible--不显示,但保留所占的空间;visible--正常显示;gone:不显示,且不保留所占的空间(在不显示的时候尽量用这个,另外需要注意的是在退出Activity时候,需要在Activity生命周期(onDestry)中释放)防止出现内存泄漏(关于内存泄漏问题可以参考我的个人博客 Android内存优化--LeakCanary使用详解)。

今天在用leakcanary测试项目的时候,无意中在用VideoView播放本地视频时,出现内存泄漏问题(如下图所示),提示是AudioManager类出现的, 后面百思不得其解,因为代码中Context没有被长生命周期的所引用,为什么还会出现泄漏呢?

Android应用加载布局的时候有时候会出现重叠布局或者重叠组件--动态控制组件的显示或者隐藏

后面通过google才发现原来是setVideoPath()导致的,VideoView内部的AudioManager会对Activity持有一个强引用,而AudioManager的生命周期比较长,导致这个Activity始终无法被回收,这个bug直到2015年5月才被谷歌修复。

后面也相应的找到了解决方法,需要重写如下方法

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(new ContextWrapper(newBase) {
        @Override
        public Object getSystemService(String name) {
            if (Context.AUDIO_SERVICE.equals(name))
                return getApplicationContext().getSystemService(name);
            return super.getSystemService(name);
        }
    });
}