缘起

上一篇博文中讲到了几种实现全屏显示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. 关于Windows窗口框架

    我们知道Windows的窗口消息处理函数是C方式, 面向过程的, 所以窗口框架的基本任务就是将它转成面向对象的方式, 确切的说如何将消息处理函数第一参数HWND转成对象指针. 关于这个问题, 其实网上 ...

  2. [开源]微信在线信息模拟测试工具(基于Senparc.Weixin.MP开发)

    目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具. 测试工具 ...

  3. Java-条件语句、循环语句练习

    题目一:一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米)? double height=0.08; for(int i=1;i>0;i++) { heig ...

  4. 爱上MVC~为非法进行Action的用户提供HttpStatusCodeResult

    回到目录 对一MVC来说,它有Controller和Action,其中Action用来为页面提供数据和相关逻辑,并最后将页面渲染出来,而有些action是需要一些参数的,如文章的最终页,可能需要一个I ...

  5. mybatis结合分页的使用及解析.

    首先说明: 这里分页是使用了SSM框架+ jsp 来做的, 当然分页还有其他的很多做法, 比如easyUI自带的分页效果. 但是这些原理都是很相似的, 再次只做为学习总结之用. 一, 效果图这里的截图 ...

  6. Atitit 知识图谱的数据来源

    Atitit 知识图谱的数据来源   2. 知识图谱的数据来源1 a) 百科类数据2 b) 结构化数据3 c) 半结构化数据挖掘AVP (垂直站点爬虫)3 d) 通过搜索日志(query record ...

  7. VUX 移动前端框架使用文档

    VUX 移动前端框架使用文档 https://owlaford.gitbooks.io/vux-mobile-framework/content/index.html

  8. KnockoutJS 3.X API 第四章(13) template绑定

    目的 template绑定(模板绑定)使用渲染模板的结果填充关联的DOM元素. 模板是一种简单方便的方式来构建复杂的UI结构 . 下面介绍两种使用模板绑定的方法: 本地模板是支持foreach,if, ...

  9. 快速入门系列--MVC--04模型

    model元数据 闲来继续学习蒋金楠大师的ASP.NET MVC框架揭秘一书,当前主要阅读的内容是Model元数据的解析,即使是阅读完的现在,仍然有不少细节不是特别明白.好在这部分内容主要是关于Raz ...

  10. sql server 链接到本地实例出错

    我在使用VS2010测试package的时候,突然发现sql server 链接到本地实例出错,出错信息如下: “ A network-related or instance-specific err ...