缘起

上一篇博文中讲到了几种实现全屏显示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. QQ揭秘:如何实现窗体靠边隐藏?【低调赠送:QQ高仿版GG 4.2 最新源码】

    QQ有个靠边隐藏的功能,使用起来很方便:在屏幕上拖动QQ的主窗体,当窗体的上边沿与屏幕的上边沿对齐时,主窗体就会duang~~地隐藏起来,当将鼠标移到屏幕上边沿的对应区域时,主窗体又会duang~~显 ...

  2. RCP:美化基于eclipse3.7.2的RCP界面

    从e4开始,eclipse rcp界面具备了深度自定义的能力. 但是在eclipse3.7.2上,几乎没有提供能够用于修改界面的外部接口. 这里介绍一种方式来自定义你自己的eclipse rcp. 先 ...

  3. objective-c(代码块)

    objective-c代码块(block)对写惯C语言的人非常熟悉,就类似一个函数指针,指向一个代码段的首地址: 给出简单例子如下: int main(int argc, const char * a ...

  4. 说说WeakReference弱引用

    WeakReference弱引用概述 http://www.cnblogs.com/xrq730/p/4836700.html,关于Java的四种引用状态具体请参看此文 Java里一个对象obj被创建 ...

  5. 自制Unity小游戏TankHero-2D(2)制作敌方坦克

    自制Unity小游戏TankHero-2D(2)制作敌方坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  6. xml存储bug

    最近遇到了一个bug,详细情况如下:用linq to xml写xml文件,在加载的时候代码为xDocument.Load(filePath),保存的时候为xDocument.Save(filePath ...

  7. LINQ to Entities不识别方法***,因此该方法无法转换为存储表达式

    我的程序里有这么一段代码: order.OrderExpressInfo = (from oei in orderExpressRepository.Entities where oei.OrderI ...

  8. salesforce 零基础学习(二十三)数据记录导出至excel(自定义报表导出)

    我们都知道,报表有个功能为导出excel,但是有的时候客户需求往往标准的报表达不到,比如导出excel,其中本月修改的数据字段标红,如下图所示. 这就需要我们去写VF来实现此功能. 需求:将数据表记录 ...

  9. pycharm快捷键 - 官方全

    pycharm快捷键 - 官方全 Ctrl + F12 显示文件内的成员,继承的成员

  10. java基础,继承类题目:编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E

    21.编写一个Java应用程序,该程序包括3个类:Monkey类.People类和主类 E.要求: (1) Monkey类中有个构造方法:Monkey (String s),并且有个public vo ...