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,它使创建需要与用户界面交互的长时间运行的任务变得更简单。

  • 1
  • 2
  • 下一页

相关内容