`

Android单线程模型相关概念详解(转)

 
阅读更多

 

    Android单线程模型的相关内容将会在这篇文章中进行一个详细的分析。大家可以对这一知识点进行一个详细的了解,方便将来的应用。

     

    我们今天将会在这篇文章中为大家详细介绍有关Android单线程模型的相关内容。希望初学者们可以通过本文介绍的内容对这一概念有一个充分的认识,并从中对这一系统有一个深刻的认识。

     

    当第一次启动一个Android程序时,Android会自动创建一个称为“main”主线程的线程。这个主线程(也称为UI线程)很重要,因为它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与Andriod控件交互的线程。比如,当你在屏幕上按下一个按钮后,UI线程会把这个事件分发给刚按得那个按钮,紧接着按钮设置它自身为被按下状态并向事件队列发送一个无效(invalidate)请求。UI线程会把这个请求移出事件队列并通知按钮在屏幕上重新绘制自身。

     

    Android单线程模型会在没有考虑到它的影响的情况下引起Android应用程序性能低下,因为所有的任务都在同一个线程中执行,如果执行一些耗时的操作,如访问网络或查询数据库,会阻塞整个用户界面。当在执行一些耗时的操作的时候,不能及时地分发事件,包括用户界面重绘事件。从用户的角度来看,应用程序看上去像挂掉了。更糟糕的是,如果阻塞应用程序的时间过长(现在大概是5秒钟)Android会向用户提示一些信息,即打开一个“应用程序没有相应(application not responding)”的对话框。

     

    如果你想知道这有多糟糕,写一个简单的含有一个按钮的程序,并为按钮注册一个单击事件,并在事件处理器中调用这样的代码Thread.sleep(2000)。在按下这个按钮这后恢复按钮的正常状态之前,它会保持按下状态大概2秒钟。如果这样的情况在你编写的应用程序中发生,用户的第一反应就是你的程序运行很慢。

     

    现在你知道你应该避免在UI线程中执行耗时的操作,你很有可能会在后台线程或工作者线程中执行这些耗时的任务,这样做是否正确呢?让我们来看一个例子,在这个例子中按钮的单击事件从网络上下载一副图片并使用ImageView来展现这幅图片。代码如下:

     

     

  1. public void onClick( View v ) {   
  2. new Thread( new Runnable() {   
  3. public void run() {   
  4. Bitmap b = loadImageFromNetwork();   
  5. mImageView.setImageBitmap( b );   
  6. }   
  7. }).start();   
  8. }   
  9. public void onClick( View v ) {  
  10. new Thread( new Runnable() {  
  11. public void run() {  
  12. Bitmap b = loadImageFromNetwork();  
  13. mImageView.setImageBitmap( b );  
  14. }   
  15. }).start();  

 

这段代码好像很好地解决了你遇到的问题,因为它不会阻塞UI线程。很不幸,它违背了Android单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。在这段代码片段中,在一个工作者线程中使用ImageView的方法,这回引起一些很古怪的问题。查处这个问题并修复这个bug会很困难而且也很耗时。

 

Andriod提供了几种在其他线程中访问UI线程的方法。或许你已经对其中的一些方式很熟悉,但下面是一个更全面的列表:

  1. Activity.runOnUiThread( Runnable )   
  2. View.post( Runnable )   
  3. View.postDelayed( Runnable, long )   
  4. Hanlder  

上面的任何一个类或方法都可以修复我们前面代码中出现的问题。

 

 

  1. public void onClick( View v ) {   
  2. new Thread( new Runnable() {   
  3. public void run() {   
  4. final Bitmap b = loadImageFromNetwork();   
  5. mImageView.post( new Runnable() {   
  6. mImageView.setImageBitmap( b );   
  7. });   
  8. }   
  9. }).start();   
  10. }   
  11. public void onClick( View v ) {  
  12. new Thread( new Runnable() {  
  13. public void run() {  
  14. final Bitmap b = loadImageFromNetwork();  
  15. mImageView.post( new Runnable() {  
  16. mImageView.setImageBitmap( b );  
  17. });  
  18. }  
  19. }).start();  

 

很不幸的是这些类或方法同样会使你的代码很复杂很难理解。然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。为了解决这个问题,Android 1.5提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。

 

在Android 1.0和1.1中具有与AsyncTask相同功能的类UserTask。它提供了完全一样的API,你需要做的只是把它的代码拷贝的你的程序中。

 

AsyncTask的目标是替你管理你的线程。前面的代码可以很容易地使用AsyncTask重写。

 

 

  1. public void onClick( View v ) {   
  2. new DownloadImageTask().execute
    ( "http://example.com/image.png" );   
  3. }   
  4. private class DownloadImageTask extends AsyncTask {   
  5. protected Bitmap doInBackground( String... urls ) {   
  6. return loadImageFormNetwork( urls[0] );   
  7. }   
  8. protected void onPostExecute( Bitmap result ) {   
  9. mImageView.setImageBitmap( result );   
  10. }   
  11. }   
  12. public void onClick( View v ) {  
  13. new DownloadImageTask().execute
    ( "http://example.com/image.png" );  
  14. }  
  15. private class DownloadImageTask extends AsyncTask {  
  16. protected Bitmap doInBackground( String... urls ) {  
  17. return loadImageFormNetwork( urls[0] );  
  18. }  
  19. protected void onPostExecute( Bitmap result ) {  
  20. mImageView.setImageBitmap( result );  
  21. }  

 

正如你看到的,使用AsyncTask必须要继承它。使用AsyncTask非常重要的是:AsyncTask的实例必须在UI线程中创建而且只能被使用一次。你可以使用预读AsyncTask的文档来来了解如何使用这个类,下面大概地了解一下它是如何工作的:

你可以使用泛型参数制定任务的参数、中间值(progress values)和任何的最终执行结果

doInBackground()方法会自动地在工作者线程中执行

onPreExecute()、onPostExecute()和onProgressUpdate()方法会在UI线程中被调用

doInBackground()方法的返回值会被传递给onPostExecute()方法

在doInBackground()方法中你可以调用publishProgress()方法,每一次调用都会使UI线程执行一次onProgressUpdate()方法

你可以在任何时候任何线程中取消这个任务

除了官方的文档,你可以阅读Shelves和Photostream源代码中的几个复杂的示例。我强烈地推荐阅读Shelves的源代码,它会使你知道如何在配置更改之间持久化任务以及在activity被销毁时正确的取消任务。

 

不管是否使用AsyncTask,始终记住以下两个关于Android单线程模型的准则:不要阻塞UI线程以及一切Android UI操作都在UI线程中执行。AsyncTask仅仅是使你能够更容易地遵守这两条准则。




 

分享到:
评论

相关推荐

    Android 单线程模型详解及实例

    我们今天将会在这篇文章中为大家详细介绍有关Android单线程模型的相关内容。希望初学者们可以通过本文介绍的内容对这一概念有一个充分的认识,并从中对这一系统有一个深刻的认识。 当第一次启动一个Android程序时,...

    Android多线程处理 详解

    Android采用了单线程模型,即所有的UI操作都必须在主线程中执行。这是因为Android UI组件并未设计为线程安全的。这种设计确保了UI的一致性和稳定性。 **单线程模型的特点:** - **主线程:** 主线程负责处理UI相关...

    详解Android进程和线程

    由于Android遵循单线程模型,UI操作不是线程安全的,所有与用户界面相关的操作必须在UI线程中执行,否则可能会导致应用无响应(ANR)。 然而,为了提高性能和响应性,开发者可以创建额外的线程来执行耗时任务,避免...

    android 线程详解 各种经典 完整代码

    5. IntentService:用于后台执行耗时任务,单线程,任务完成后自动停止服务。 三、线程同步与通信 1. Synchronized:用于保证线程安全,防止多线程环境下数据不一致。 2. Wait/Notify:Object类中的方法,用于线程...

    Android中子线程和UI线程通信详解

    2.首先在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。 3.Handler: (1).概念: Handler是沟通Activity 与Thread/runnable的桥梁。而Handler是...

    Android底层结构-Service线程详解

    本文将详细介绍Android中的`Service`及其线程模型,并通过五个具体实例来展示如何在不同场景下使用`Service`,以及如何实现进程间的通信。 #### 二、Service线程模型概述 在深入讨论具体的示例之前,我们先来了解...

    android多线程

    ### Android多线程详解 #### 一、进程与线程概览 在深入探讨Android多线程之前,我们首先理解进程和线程的基本概念。**进程**是正在运行的程序实例,每个进程拥有自己独立的内存空间和系统资源。而**线程**则是...

    Android 典型技术模块开发详解 pdf

    《Android典型技术模块开发详解》这本书是为初入Android开发领域的工作者量身打造的指南,旨在帮助读者深入理解和掌握Android各个关键模块的开发技术。在本文中,我们将详细探讨书中可能涉及的重要知识点,并尽可能...

    Android 线程 多线程 Multi-thread

    ### Android中的线程与多线程技术...本文介绍了Android中线程的相关概念、使用方法及其同步机制。合理运用线程不仅可以提高程序的性能,还能增强用户体验。在实际开发中,应根据具体需求选择合适的线程模型和技术方案。

    Android中线程间通信.pdf

    理解单线程模型对开发者来说至关重要。如果在设计程序时不考虑这一点,很可能会导致应用性能低下。例如,如果主线程正在进行一项耗时的操作(如从网络下载大文件或访问数据库),这可能会阻塞主线程,导致无法及时...

    《android核心技术与实例详解》源码(完整版)

    《Android核心技术与实例详解》是Android开发者们常常参考的一本技术书籍,其源码的完整版为学习者提供了深入理解Android开发的宝贵资源。这本书涵盖了Android应用开发的多个重要方面,包括但不限于UI设计、数据存储...

    Android系统原理及开发要点详解课件

    Android系统是全球最广泛...总的来说,“Android系统原理及开发要点详解”课程将全面解析Android开发中的重要概念和技术,帮助学员从基础到高级,系统地掌握Android开发的各个环节,提升个人在移动开发领域的专业素养。

    android MediaProvider和MediaScanner详解

    Android系统中的MediaProvider和MediaScanner是两个与媒体文件管理紧密相关的组件。MediaProvider是Android系统中用于管理媒体文件的Content Provider,而MediaScanner则是与之协同工作的一个后台服务,它负责扫描...

    android四大组件详解

    在Android系统中,四大组件是构建应用程序的核心元素...同时,理解Android的进程和线程模型,以及如何处理组件间的通信,也是非常重要的。在实际开发中,应参考官方文档,结合示例代码(如API Demos)进行学习和实践。

    android系统原理及开发要点详解课件

    此外,理解线程模型和异步编程(如AsyncTask、IntentService或使用Handler/Looper)也是必要的,它们可以帮助开发者实现多任务处理,提高用户体验。 在Android开发中,UI设计遵循Material Design指南,以提供一致且...

    Android应用开发详解教材源码(下册)

    《Android应用开发详解教材源码(下册)》是一本深度剖析Android应用开发的实践教程,包含8个单元,涵盖了30多个实例源码。这些实例旨在帮助读者深入理解Android平台上的应用程序设计与实现,从基础到高级,全方位地...

    Android应用开发详解(PDF+全部的源代码

    在Android应用开发详解中,你将深入学习到构建Android应用程序所需的各种技术和概念。这份资源包含一个PDF文档,可能涵盖了从基础到高级的Android开发主题,以及与之配套的全部源代码,这使得学习过程更具实践性。 ...

    Android系统原理与开发要点详解-培训课件.zip

    4. **Android权限管理**:Android使用基于声明的权限模型,应用在清单文件中声明所需权限,用户在安装时或运行时授予。 5. **Android UI设计**:Android使用XML布局文件创建用户界面,包括线性布局、相对布局、网格...

Global site tag (gtag.js) - Google Analytics