Threading(in thread main)

PainlessThreadingThisarticlediscussesthethreadingmodelusedbyAndroidapplicationsandhowapplicationscanensurebestUIperformancebyspawningworkerthreadstohandlelong-runningoperat

大家好,又见面了,我是你们的朋友全栈君。Painless Threading

This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.

本文讨论Android中的线程模型,以及应用如何通过产生worker threads来处理长时间操作以确保最佳的UI性能,而不是在主线程中处理这些任务。本文还介绍了与Android UI工具包组件中的主线程进行交互以及产生worker threads的APIs。

The UI thread

UI线程

When an application is launched, the system creates a thread called “main” for the application. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets, including drawing events. It is also the thread where your application interacts with running components of the Android UI toolkit.

当应用被启动时,系统创建一个主线程(main thread)。主线程也被称为UI线程(UI thread)管理事件的发布,如drawing events.它也是与Android UI工具包的运行组件交互的线程.

This single-thread model can yield poor performance unless your application is implemented properly. Specifically, if everything is happening in a single thread, performing long operations such as network access or database queries on the UI thread will block the whole user interface. No event can be dispatched, including drawing events, while the long operation is underway. From the user’s perspective, the application appears hung. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous “application not responding” (ANR) dialog.

除非你的应用是正确的,否则这种单线程模型有可能产生低效的性能。特别地,若所有事件都发生在在单一线程中,执行长操作,如在UI线程中访问网络或者数据库查询将阻塞整个用户界面。此时任何其它事件,如drawing events都不会被派发。从用户的角度,应用给人感觉被挂起了。更糟糕地是,若UI线程阻塞时间多达几秒,用户会以为”application not responding”(ANR).

To summarize, it’s vital to the responsiveness of your application’s UI to keep the UI thread unblocked. If you have long operations to perform, you should make sure to do them in extra threads (background or worker threads).

总之,保证主线程非阻塞非常重要。若你执行长时间操作,你需要在其它的线程(后台线程或工作线程)中执行。

Here’s an example of a click listener downloading an image over the network and displaying it in an ImageView:

以下给出单击监听下载一张图片并将其显示在ImageView中的例子:

public void onClick(View v) {

  new Thread(new Runnable() {

    public void run() {

      Bitmap b = loadImageFromNetwork();

      mImageView.setImageBitmap(b);

    }

  }).start();

}

At first, this code seems to be a good solution to your problem, as it does not block the UI thread. Unfortunately, it violates the single-threaded model for the UI: the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread. In this piece of code above, the ImageView is manipulated on a worker thread, which can cause really weird problems. Tracking down and fixing such bugs can be difficult and time-consuming.

这段代码貌似没问题,因为它不会阻塞UI线程。然而,它违反了UI单线程模型:Android UI工具集并不是线程安全的,它而且必须在UI线程中执行。所以以上代码中,ImageView在一个工作线程中被执行,这可能导致非常奇怪的问题。调试这种bugs又困难又浪费时间。

Android offers several ways to access the UI thread from other threads. You may already be familiar with some of them but here is a comprehensive list:

Android提供多种方式使其它线程访问UI线程。

以下给出一种很熟悉的步骤访问UI线程:

1).Activity.runOnUiThread(Runnable)

2).View.post(Runnable)

3).View.postDelayed(Runnable, long)

4).Handler

public void onClick(View v) {

  new Thread(new Runnable() {

    public void run() {

      final Bitmap b = loadImageFromNetwork();

      mImageView.post(new Runnable() {

        public void run() {

          mImageView.setImageBitmap(b);

        }

      });

    }

  }).start();

}

Unfortunately, these classes and methods could also tend to make your code more complicated and more difficult to read. It becomes even worse when your implement complex operations that require frequent UI updates.

不幸地是,这些类与方法只会使你的代码难以维护。特别是在你实现需要频繁的UI更新操作时这种方法使你的实现更加复杂。

To remedy this problem, Android 1.5 and later platforms offer a utility class called AsyncTask, that simplifies the creation of long-running tasks that need to communicate with the user interface.

为了解决这个问题,Android 1.5+提供了一个工具类AsyncTask来简化一个需要与用户界面交互的长时间运行的任务的创建。

An AsyncTask equivalent is also available for applications that will run on Android 1.0 and 1.1. The name of the class is UserTask. It offers the exact same API and all you have to do is copy its source code in your application.

Android 1.0和1.1中提供了一个AsyncTask类的等价类UserTask,它提供了几乎一模一样的API.

The goal of AsyncTask is to take care of thread management for you. Our previous example can easily be rewritten with AsyncTask:

AsyncTask的目标是关注线程管理,之前那个例子可用AsyncTask重写为:

public void onClick(View v) {

  new DownloadImageTask().execute(“http://example.com/image.png”);

}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {

     protected Bitmap doInBackground(String… urls) {

         return loadImageFromNetwork(urls[0]);

     }

     protected void onPostExecute(Bitmap result) {

         mImageView.setImageBitmap(result);

     }

}

As you can see, AsyncTask must be used by subclassing it. It is also very important to remember that an AsyncTask instance has to be created on the UI thread and can be executed only once. You can read the AsyncTask documentation for a full understanding on how to use this class, but here is a quick overview of how it works:

正如你所看到的,AsyncTask需要被继承。注,AsyncTask实例必段在UI线程中创建并且只被执行一次。你可以阅读AsyncTask文档来了解更详细的使用。以下给出AsyncTask的简介:

1).You can specify the type of the parameters, the progress values and the final value of the task

你需要指明task的参数类型,进度值以及最终值

2).The method doInBackground() executes automatically on a worker thread

doInBackground()方法在一个工作线程中自动执行

3).onPreExecute(), onPostExecute() and onProgressUpdate() are all invoked on the UI thread

onPreExecute(), onPostExecute()和onProgressUpdate()都在UI线程中执行

4).The value returned by doInBackground() is sent to onPostExecute()

doInBackground()方法返回的值被发送给onPostExecute()

5).You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread

你可以在doInBackground()方法中的任何时候调用publishProgress()来执行UI线程中的进度更新任务onProgressUpdate()

6).You can cancel the task at any time, from any thread

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

Regardless of whether or not you use AsyncTask, always remember these two rules about the single thread model:

不论你是否使用AsyncTask,对于单线程模记住以下两条准则很重要:

1).Do not block the UI thread, and —— 不要阻塞UI线程

2).Make sure that you access the Android UI toolkit only on the UI thread. —— 确保只在UI线程中访问Android UI工具集

详情请见:http://developer.android.com/resources/articles/painless-threading.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/128924.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 啥是SBC_sbc是什么意思的缩写

    啥是SBC_sbc是什么意思的缩写SBC简介SBC应用SBC功能★SBC简介会话边界控制器SessionBorderController,即会话边界控制器SBC已经逐渐成为NGN和IMS网络的标准配置产品(如同Lanswitch和路由器)。也被广泛称为BAC(边界接入控制器),定位在IMS网络的ABG(accessbordergateway),解决NGN业务部署中遇到的NAT/FW穿越

    2022年9月12日
    0
  • Python进阶(九)Python陷阱:Nonetype「建议收藏」

    Python进阶(九)Python陷阱:Nonetype「建议收藏」而在上面的程序中,虽然高阶函数calc_prod()有返回值ff,但是ff()却没有返回值,则传递到外层函数calc_prod()同样没有返回值,故输出了。针对这一问题,自己在IDEA中进行了调试,发现果然多输出了一行None。只有值可以改变,其他只读。之所以出现是因为定义了一个变量或函数,却没有值或者返回值,因此会默认值为。发现b的值确实为None,且其类型为NoneType。若代码改为如下所示,则可以完美实现列表的输出。它不支持任何运算也没有任何内建方法。对象具有三个特性:身份、类型、值。

    2022年10月22日
    0
  • oracle数据库去重查询_oracle高效去重

    oracle数据库去重查询_oracle高效去重数据库多字段去重方法介绍:distinct关键字、groupby 、row_number()over()

    2022年10月1日
    0
  • 源码编译安装memcached和PHP扩展memcache整理总结

    源码编译安装memcached和PHP扩展memcache整理总结

    2022年2月17日
    34
  • JavaScript—网络编程(3)-Object、String、Array对象和prototype属性[通俗易懂]

    JavaScript—网络编程(3)-Object、String、Array对象和prototype属性[通俗易懂]本节学习JavaScript的对象和方法(函数)~Object对象提供所有JScript对象通用的功能。obj=newObject([value])参数obj必选项。要赋值为Object对象的变量名。value可选项。任意一种JScript基本数据类型。(Number、Boolean、或String。)如果value为一个对象,返回不作改动的该对象。如果

    2022年5月9日
    44
  • SIGPIPE信号

    SIGPIPE信号当一个进程向某个已收到RST的套接字执行写操作时,内核向该进程发送一个SIGPIPE信号。该信号的默认行为是终止进程,因此进程必须捕获它以免不情愿地被终止。不论该进程是捕获了该信号并从其信号处理函数返回,还是简单地忽略该信号,写操作都将返回EPIPE错误。

    2022年5月7日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号