缘起

上一篇博文中讲到了几种实现全屏显示Activity内容的方法。然而实际在实现中发现了一些问题,在本篇博文中进行总结下。首先交代一下开发环境,本人使用的是Android Studio 1.5.1,因此使用Eclipse ADT开发或者低版本的SDK的时候可能不会碰到这个问题。首先看onCreate()方法中的实现代码:

 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
}

非常简单的两行代码,然而运行代码的时候应用却直接奔溃。在Android Studio中观察应用的奔溃信息,只看到一条简单的消息:threadid=1: thread exiting with uncaught exception (group=0x419f6c50)。根本无从得知哪里出的错误,因为代码本来就少,才这么两行。于是就在网上搜了一下AS的调试方法,总结了一下Android Studio中捕获异常的方法。

Android Studio捕获异常方案一

我们知道Java语言提供了try-catch机制来捕获运行时异常。因此想到,我们在排查Android运行时异常时是否也可以利用起try-catch这个工具呢?加起来就试试好了:

再次在模拟器中运行应用,可以在logcat中输出如下信息:

这时候已经可以看到具体的异常信息了:requestFeature() must be called before adding content。已经达到了我们想要的结果,但是这个方法有个缺点:就是得估计异常大致出现在什么地方,这才好用try-catch包裹它。至于这个异常代表着什么,现在先不说,再来看看第二种异常捕获方案好了。

Android Studio 捕获异常方案二

这种方案是从网上看来的,利用了Therad的一个静态方法,首先定义一个Thread.UncaughtExceptionHandler的实例,然后在程序中设置为未捕获异常的默认处理器:

 private final Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable ex) {
Log.e("TestApplication", "Uncaught exception is: ", ex);
// log it
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
Thread.setDefaultUncaughtExceptionHandler(handler); super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
}

这种方案只需要一个Thread.UncaughtExceptionHandler的实例即可,不需要估计异常发生的大致位置。得到的输出信息如下:

异常信息也是非常的明了,能够看出异常抛出的堆栈信息,从而更快的跟踪定位Bug的所在。那么这个异常到底说明了什么呢?看字面意思是,requestWindowFeature()方法必须在添加视图之前先调用。可是以前也是这么用的啊,也没见出现过这种异常。于是又搜索了一番才在StackOverflow上发现了解决方案。简单的来说就是将requestWindowFeature()放到第一行调用。为什么呢?关键原因在于,我在Android Studio 1.5里面新建的工程Activity默认是继承自AppCompatActivity类。在那篇帖子里面提到了一些解决方法:(1)要么把基类从AppCompatActivity(或者ActionBarActivity)改成Activity。这样就可以不用将requestWindowFeature放到第一行了。(2)或者是使用supportRequestWindowFeature()方法代替requestWindowFeature()方法,这样也不用放到第一行去调用。这三种方法随意一种都可以解决问题。至于原因,帖子里面也是众说纷纭,不好解释。不过大致的原因,是由于Google为Android提供的兼容包导致的问题。

ActionBarActivity和AppCompatActivity的关系

在StackOverflow的那篇帖子中,有提到一个已经被Google废弃的基类ActionBarActivity。这个类在现在的SDK中已经被废弃使用了,从源代码来看,ActionBarActivity现在就是继承自AppCompatActivity的一个空类,紧紧是为了向下兼容考虑。Google已经建议开发者逐步使用ToolBar来代替以前版本中的ActionBar了,因此废弃ActionBarActivity,在新版本中使用AppCompatActivity做基类也是情理之中的事情了。

那么,AppCompatActivity新在哪里呢?根据文档说明,AppCompatActivity是一个设计实现的更通用的类,内部使用了AppCompatDelegate作为逻辑实现核心。这个delegate的存在,是为了更好的贯彻Google推行的Material Design的设计理念。有时你可能想在一个旧版本的Activity(既不是继承自ActionBarActivity又不是继承AppCompatActivity的类)中使用Material Design的组件。此时,这个delegate能够很好的满足这个要求。只要在这个旧式Activity中实现AppCompatDelegate的相关方法,然后重写旧式Activity中的addContentView()、setContentView()等方法,并在这些方法中回调AppCompatDelegate中的对应方法,即可为旧式Activity添加具备Material Design风格的视图组件。

参考

Android开发中遇到的requestFeature() must be called before adding content异常的更多相关文章

  1. Android开发中java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}

    Android开发中java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}: java.lang.NullPoi ...

  2. Android学习探索之Java 8 在Android 开发中的应用

    前言: Java 8推出已经将近2年多了,引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时减化了各种设计模式的实现方式,是Java有史以来最重要的更新.但是Android上, ...

  3. android开发中fragment获取context

    在用到fragment时无法使用.this来指定当前context内容,android开发中fragment获取context,可以使用getActivity().getApplicationCont ...

  4. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  5. Android开发中的输入合法性检验

    Why ? 合法性检查对于程序的健壮性具有重要作用.在Android开发中,良好的合法性检查设计机制可以使程序更加清晰,产生bug更少,交互更加友好. What ? 合法性检查的目的在于确定边界.对于 ...

  6. 在android开发中使用multdex的方法-IT蓝豹为你整理

    Android系统在安装应用时,往往需要优化Dex,而由于处理工具DexOpt对id数目的限制,导致其处理的数目不能超过65536个,因此在Android开发中,需要使用到MultiDex来解决这个问 ...

  7. 怎样实现了捕获应用中的日志在android开发中

    怎样实现了捕获应用中的日志在android开发中,大家可研究一下. Process mLogcatProc = null; BufferedReader reader = null; try { mL ...

  8. Android开发中Eclispe相关问题及相应解决(持续更新)

    1.Eclipse项目中的Android Private Libraries没有自动生成. 一般而言,在Android开发中,项目中引用到的jar包会放到项目目录中的libs中,引入库会放到Andro ...

  9. Android开发中的问题及相应解决(持续更新)

    最近博客写的少了,以后还得经常更新才行. ------------------------------------------------------------ 1.特定业务需求下try cath ...

随机推荐

  1. javascript的执行和预解析

    很久以前遇到过一个面试题目,的的确确是面试官问我的问题,下面是这个问题的代码部分.由于年少无知,没有回答上,被无情pass了. var u ='hello world'; ;(function(){ ...

  2. 设计模式之美:Template Method(模板方法)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Template Method 模式结构样式代码. 意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. Templat ...

  3. 一道原生js题目引发的思考(鼠标停留区块计时)

    我瞎逛个啥论坛,发现了一个题目,于是本着练手的心态就开始写起来了,于是各种问题接踵而至,收获不小. 题目是这样的: Demo: mouseenter与mouseover区别demo 跨浏览器的区块计数 ...

  4. [php入门] 2、基础核心语法大纲

    1 前言 最近在学PHP,上节主要总结了PHP开发环境搭建<[php入门] 1.从安装开发环境环境到(庄B)做个炫酷的登陆应用>.本节主要总结PHP的核心基础语法,基本以粗轮廓写,可以算作 ...

  5. 我心中的核心组件(可插拔的AOP)~调度组件quartz.net

    回到目录 quartz.net是一个任务调度组件,它可以灵活的设置你的调试方式,按时间,按日期,按周期都可以很容易的实现,quartz不仅可以用在web中,而且还可以部署在winform,winser ...

  6. 遍历后台的List,让前台的多选宽被选中

    后端代码: /** * 获取优惠卷分页信息 * * * @param ph * 包括查询条件以及分页查询条件 * */ @Override public DataGrid<AppCmsCoupo ...

  7. 在Ubuntu搭建.NET Core环境

    Ubuntu16.04配置.net core环境   Ubuntu 16.04 desktop下载地址:http://www.ubuntu.com/desktop 本次是用vmware安装该系统.   ...

  8. APP 版本更新 流程(已上架APP,提交新版本)

    背景: 今天发布app的新版本, 可是无奈换了电脑, 没有了以前上架时候的发布证书和描述文件. 但是没关系, 依然可以上传成功,哈哈哈~ 虽然走了很多弯路 - -|| 如果是向 App Store 提 ...

  9. HTTP协议从入门到大牛,初识HTTP协议(学习笔记)

    HTTP数据传输协议 当访问一个网页时,浏览器会向服务器发起一条HTTP请求,接着服务器会去寻找相应的资源,如果请求成功,就会把这个对象,对象类型,对象长度以及其他的信息放在HTTP响应中,发送给客户 ...

  10. SQL Server中一个隐性的IO性能杀手-Forwarded record

    简介     最近在一个客户那里注意到一个计数器很高(Forwarded Records/Sec),伴随着间歇性的磁盘等待队列的波动.本篇文章分享什么是forwarded record,并从原理上谈一 ...