很多新手开发程序的时候,或者将原来跑在Android 2.X上的程序迁移到Android 3.x以上的时候经常会莫名其妙的出现崩溃(Crash)。从我的经验来看,这里可能有很多原因,但是最重要也是最常见的一个,可能是因为你在UI线程中做了一个耗时的操作。

什么是UI线程?


UI线程的重要性和概念是每一个Android开发者都应该谙熟于心的。每次一个应用启动后,系统会为该进程创建一个叫做"main"的线程,即UI线程,或者主线程。这个线程主要是用来分发事件到应用里面的组件和控件上的,所以很重要,同时也是各个组件间交互的桥梁。例如,如果你按下了一个按钮,UI线程就会分发这个触摸事件到这个按钮控件上,然后设置它的状态,同时发出一个绘制按钮请求(比如按钮变成按下的模样)事件队列中,随后UI线程不断的从队列中取出这个事件来让系统绘制它。

这种单线程模型可能会导致糟糕的性能除非你合适的处理。因为UI线程几乎是处理任何正在进行的事件,所以如果你在UI线程里面做了一个诸如访问网络或者查询数据库之类的耗时操作,那么就会卡住UI线程使它不能处理别的事情,这就会造成卡住界面。因为事件分发不了了,界面也没法重绘了,也没法响应用户的操作了。从用户来看,似乎程序是不响应了。

对于这种情况,及时的反馈是重要的。研究表明0.1秒是用户感受是否有立即响应的极限时间。如果耗时比这个长那么用户即会感觉系统有点迟钝,即使是几分之一秒也是令人感觉不好的。更糟糕的情况是,如果UI线程被卡住超过5秒,Android系统会直接弹出一个对话框,即ANR(“application not responding”),随后即强制关闭这个程序。

为什么你的程序会崩溃(Crash)?


为什么很多原来跑在Android 2.X上没问题的程序迁移到Android 3.x或者Android4.x以上的时候经常会莫名其妙的出现崩溃(Crash)?这是因为Honeycomb(3.x)和ICS(4.x)版本以后对于检查是否在UI线程中做耗时操作这一禁忌更加严格了,即它会直接抛出异常。

比如,如果在Android 3.x以上的机器上跑的程序在UI线程中访问网络,则会直接抛出一个NetworkOnMainThreadException异常:

E/AndroidRuntime(673): java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example/com.example.ExampleActivity}: android.os.NetworkOnMainThreadException

下面是Android Developer上对该异常的解释:

  • A NetworkOnMainThreadException is thrown when an application attempts to perform a networking operation on its main thread. This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.

其他不可以在UI线程上做的事情比如有:

  1. 打开一个套接字(socket, eg: new Socket())
  2. 发送一个Http请求
  3. 连接一个远程的MySql数据库
  4. 下载文件

如果你想要在UI线程上做这些事情,请另起一个工作线程来执行。最简单的一个方式即使用Android所提供的AsyncTask,它可以让你在UI线程上做异步的操作。AsyncTask将会在一个工作线程上做耗时的操作,最后会返回结果给UI线程,这样子你就不需要自己去创建或者管理一个Thread。

所以最后,记住最重要的一点,不要直接在UI线程中做耗时的操作。

Android开发新手第一要素的更多相关文章

  1. Android开发新手常见的10个误区

    在过去十年中最流行的移动应用开发开发平台中,我们认为,Android平台是一个新开发的最方便的平台.一个廉价的工具,友好的开发者社区,众所周知的编程语言(Java),使得开发Android应用程序从未 ...

  2. Android开发新手学习总结(一)——使用Android Studio搭建Android集成开发环境

    [新手连载]一:使用Android Studio搭建Android集成开发环境http://bbs.itcast.cn/forum.php?mod=viewthread&tid=87055&a ...

  3. 【Android开发】 第一课 环境搭建教程

    Windows 开发环境部署: Android Studio 中文社区:http://www.android-studio.org/ 本教程将分为五个步骤来完成Android开发环境的部署. 第一步: ...

  4. Android开发新手问题

    因为最近在用空闲时间学习Android开发,期间确实遇到了一些问题.而且因为我之前在公司里一直都是在使用Eclipse进行开发,所以最初我学习Android时也就选择了Google的包含android ...

  5. Android开发的第一天

    不管做什么开发都是有开始的,对于开发的话开始要的准备的就是开发工具了  安装开发工具配置开发工具好了不多说了现在我来说怎么样安装和配置安卓的开发工具吧 第一首先就是要下载一个JDK (Java SE ...

  6. Android开发新手教程--Android应用程序结构

    一.新HelloWorld工程: 1.打开Eclipse.点击"File"->"New"->"Project"-Android ...

  7. Android开发-之第一个程序:HelloWorld!

    小编觉得不管学习什么编程的时候,第一个程序都是要求打印输出一个"HelloWorld!",那就从最简单的HelloWorld开始吧!哈哈~~~~ 一.创建一个Android工程 1 ...

  8. Android开发新手学习总结(六)——android开发目录结构【图文版】

    转载链接:http://bbs.itcast.cn/thread-87059-1-1.html?rss 既然已经搭建好环境了,那就对Android Studio中项目目录结构做个简单的了解了,这里以最 ...

  9. Android开发新手HelloWorld解析

    首先看这个 HelloWorld 类. Java代码public class HelloWorld extends Activity {       /** Called when the activ ...

随机推荐

  1. 使用MiniProfiler调试ASP.NET MVC网站性能

    MiniProfiler 以前开发Webform的时候可以开启trace来跟踪页面事件,这对于诊断程序的性能是有很大的帮助的,起到事半功倍的作用,今天我就来谈用mvc开 发项目的调试和性能监控.EF框 ...

  2. python代码学习day03-序列化学习pickle及json

    #!/usr/bin/env python #coding:utf8 import pickle,json import datetime dic1 = {'name':'alex', 'age':4 ...

  3. Less里css表达式的写法

    项目中用的grunt-contrib-less, 写了以下less代码 .mapfix{ position: fixed; top:10px; width: 430px; z-index: 100; ...

  4. JavaScript中的直接量与初始器的区别

    很多代码优化及公司规范都会提到 写对象不应该 var obj = new Object() 而应该 var obj = {} 写数组不应该 var arr = new Array() 而应该 var ...

  5. 计算几何--判断两条线段相交--poj 2653

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8862   Accepted: 3262 De ...

  6. 计算1到最大的n位十进制数 ——大数解决

    要求:输入一个数字n,按照顺序打印出从1到最大的n为十进制.比如输入3,则打印出1.2.3……一直到最大的3位数999 这个看起来好像很简单啊.巴拉巴拉,已经得出了下面的代码 /** * 注意: 错误 ...

  7. UEdit初始化加载内容偶尔失败,解决

    var ue1 = UE.getEditor('aaa',{toolbars: [],autoHeightEnabled: false}); $(function(){ var content =$( ...

  8. 标准IO的缓冲问题

    在看APU时,第8章进程时, #include <stdio.h> #include <unistd.h> ; char buf[] = "a write to st ...

  9. SSIS with vertica

    使用ODBC进行连接,因为SSIS中没有直接的ODBC connection,所以使用ADO.NET的连接器. 九分钟才跑了四百来条数据. 这个图反应了SSIS的数据流速度还是可以的,但是瓶颈就在OD ...

  10. [转] KVM Internals, code and more

    KVM Kernel-based Virtual Machine Internals, code and more http://slides.com/braoru/kvm#/ What behind ...