PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法

2024-06-15 15:32

本文主要是介绍PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今日终于修复了一个非常严重的bug:
这个bug非常奇怪,我在Anroid.4.0.4或以上测试都正常,但是后来廉温说他在他的手机按一下右下角的"设置"按钮(Button),居然出现了崩溃现象(理论上会在设置按钮上弹出一popuwindow);
廉温手机系统2.3.X ;然后我用平板(系统也是2.3.x)测试下,果然出现错误;
由于平板基本报废,无法USB连接地电脑跟踪测试;一开始我没放在心上,因为几台4.0.4or以上系统都测试能正常。。
于是开了模拟器(系统2.3.3)测试,结果还是崩溃,看log日志 ,报了一个NullPointExcetion,这。。实在太费解了!
问题入口:
......
protected PopupWindow window;
......
this.window = new PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
....
这里我实例化一个 PopupWindow ,当时我没有注意,以为传入2个 MeasureSpec (  Width/Height )也就是窗体layout_height 和layout_weight ; 可以是   FILL_PARENT or  WRAP_CONTENT or 具体的高和宽!
悲剧的是,看回文档,居然是:

public PopupWindow (int width, int height)
Added in  API level 1

Create a new empty, non focusable popup window. The dimension of the window must be passed to this constructor.

The popup does not provide any background. This should be handled by the content view.

Parameters
width the popup's width
height the popup's height 

这实际上要是指定了content view 的高、宽 而不是MeasureSpec (FILL_PARENT or WRAP_CONTENT 。。)
那就奇怪了,由于 ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT 这两个常量是负数
窗体的高宽是负数,按道理是不会显示窗体的啊!而且4.0.4系统还是会个跟2.3.3报同一个错误啊! 
但为啥在系统是4.0.4的时候还是正常显示,而2.3.3却错误?
于是我翻看了源码,跟踪记录如下:
Step 1: 
249
     public PopupWindow(int widthint height) {
250
         this(nullwidthheight);     
251
     } 
        

Step    2:
 
265
     public PopupWindow(View contentViewint widthint height) {
266
         this(contentViewwidthheightfalse);  // ->
contentView = null
267
     }
   
Step 3:
   
281
     public PopupWindow(View contentViewint widthint heightboolean focusable) {
282
         if (contentView != null) {
283
             mContext = contentView.getContext();
284
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
285
         }
286
         setContentView(contentView);     // -> 在这里报了个NullPointExcetion ,再跟踪
287
         setWidth(width);
288
         setHeight(height);
289
         setFocusable(focusable);
290
     }


Step 4 :
2.3.3
系统下
 
   
376
     public void setContentView(View contentView) {
377
         if (isShowing()) {
378
             return;
379
         }
380
 
381
         mContentView = contentView;
382
 
383
         if (mContext == null) {
384
             mContext = mContentView.getContext();
385
         }
386
 
387
         if (mWindowManager == null) {
388
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
389
         }
390
     }
 
同是
Step 4 :
4.0.4 系统下
390
     public void setContentView(View contentView) {
391
         if (isShowing()) {
392
             return;
393
         }
394
 
395
         mContentView = contentView;
396
 
397
         if (mContext == null && mContentView != null) {
398
             mContext = mContentView.getContext();
399
         }
400
 
401
         if (mWindowManager == null && mContentView != null) {
402
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
403
         }
404
     }
果然~出现了非常神奇的一幕~ 原来在2.3.3的时候忘记检查
mContentView 是否为空,因为mContextView 这个对象可以在实例化一个PopupWindow 后再通过SetContextView(View view)传入
也就是说,这是算是一个系统级的小bug~ 所以在2.3.3 或以前的版本时 就会崩溃,在4.0.4 以后的都不会崩溃;这不能完全怪谷歌,谁让我没有认真看下文档呢?
这也是我第一次发现谷歌的代码漏洞XD

解决2.3.3或以下的办法就是用
1、可以用PopupWindow(Context context)这个构造方法实例化
2、mPopupWindow.setContentView(View view) 传入content view
3、mPopupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
mPopupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
这里的setWidth() setHeight() 才是是改变PopupWindow 的Width/Height MeasureSpec

转载请说明出处,鼓励原创!

这篇关于PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1063851

相关文章

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级