Android开发新手第一要素

很多新手开发程序的时候,或者将原来跑在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线程中做耗时的操作。

 

posted @ 2015-07-03 15:28  soaringEveryday  阅读(438)  评论(0编辑  收藏  举报