Handler vs AsyncTask vs Thread [关闭]

本文翻译自:Handler vs AsyncTask vs Thread [closed]

I got slightly confused about the differences between Handlers , AsyncTask and Threads in Android. 我对Android中的HandlersAsyncTaskThreads之间的区别感到有些困惑。 I've read quite a few blogs and questions here in StackOverflow. 我在StackOverflow中阅读了很多博客和问题。

Handler are background threads that provide you to communicate with the UI. Handler是后台线程,可让您与UI进行通信。 Updating a progress bar, for instance, should be done via Handler . 例如,更新进度条应该通过Handler完成。 Using Handlers you have the advantage of MessagingQueues , so if you want to schedule messages or update multiple UI elements or have repeating tasks. 使用处理程序可以获得MessagingQueues的优势,因此,如果您要安排消息或更新多个UI元素或重复执行任务。

AsyncTask are similar, in fact, they make use of Handler , but doesn't run in the UI thread, so it's good for fetching data, for instance fetching web services. AsyncTask类似,事实上,它们使用Handler ,但不在UI线程中运行,因此它对于获取数据很有用,例如获取Web服务。 Later you can interact with the UI. 稍后您可以与UI进行交互。

Thread however can't interact with the UI, provide more "basic" threading and you miss all the abstractions of AsyncTask . Thread无法与UI交互,提供更多“基本”线程,并且您错过了AsyncTask所有抽象。

However, I would like to have a socket connection run in service. 但是,我想在服务中运行套接字连接。 Should this be run in a handler or a thread, or even an AsyncTask ? 它应该在处理程序或线程中运行,还是在AsyncTask UI interaction is not necessary at all. 根本不需要UI交互。 Does it make a difference in terms of performance which I use? 它在我使用的性能方面有所不同吗?

Meanwhile, the documentation has been majorly improved. 同时, 文档已得到重大改进。


#1楼

参考:https://stackoom.com/question/TDel/Handler-vs-AsyncTask-vs-Thread-关闭


#2楼

AsyncTask is designed to perform not more than few seconds operation to be done in background (not recommended for megabytes of file downloading from server or compute cpu intensive task such as file IO operations ). AsyncTask旨在在后台执行不超过几秒的操作(不推荐用于从服务器下载的兆字节文件或计算cpu密集型任务,如文件IO操作)。 If you need to execute a long running operation, you have been strongly advised to use java native threads. 如果需要执行长时间运行的操作,强烈建议您使用java本机线程。 Java gives you various thread related classes to do what you need. Java为您提供了各种与线程相关的类,以满足您的需求。 Use Handler to update the UI Thread. 使用Handler更新UI线程。


#3楼

Thread 线

Android supports standard Java Threads . Android支持标准Java 线程 You can use standard Threads and the tools from the package “ java.util.concurrent ” to put actions into the background. 您可以使用标准线程和“ java.util.concurrent ”包java.util.concurrent的工具将操作放入后台。 The only limitation is that you cannot directly update the UI from the a background process. 唯一的限制是您无法直接从后台进程更新UI。

If you need to update the UI from a background task you need to use some Android specific classes. 如果您需要从后台任务更新UI,则需要使用某些特定于Android的类。 You can use the class “ android.os.Handler ” for this or the class “ AsyncTask 你可以使用类“ android.os.Handler ”或类“ AsyncTask

Handler 处理器

The class “ Handler ” can update the UI. Handler ”类可以更新UI。 A handle provides methods for receiving messages and for runnables. 句柄提供接收消息和可运行的方法。 To use a handler you have to subclass it and override handleMessage() to process messages. 要使用处理程序,必须将其子类化并覆盖handleMessage()以处理消息。 To process Runable , you can use the method post(); 要处理Runable ,可以使用方法post(); You only need one instance of a handler in your activity. 您只需要活动中的一个处理程序实例。

You thread can post messages via the method sendMessage(Message msg) or sendEmptyMessage . 您的线程可以通过sendMessage(Message msg)sendEmptyMessage方法发布消息。

AsyncTask 的AsyncTask

If you have an Activity which needs to download content or perform operations that can be done in the background AsyncTask allows you to maintain a responsive user interface and publish progress for those operations to the user. 如果你有一个Activity ,其需要下载的内容或执行,可以在后台进行操作AsyncTask让你保持响应用户界面和发布这些操作给用户进程。

For more information you can have a look at these links. 有关更多信息,您可以查看这些链接。

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/ http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


#4楼

After looking in depth, it's straight forward. 在深入研究之后,它是直截了当的。

AsyncTask : AsyncTask

It's a simple way to use a thread without knowing anything about java thread model . 这是一种使用线程的简单方法, 而不了解任何有关java线程模型的信息 AsyncTask gives various callbacks respective to the worker thread and main thread. AsyncTask提供了与工作线程和主线程相对应的各种回调。

Use for small waiting operations like the following: 用于小等待操作,如下所示:

  1. Fetching some data from web services and display over layout. 从Web服务获取一些数据并在布局上显示。
  2. Database query. 数据库查询。
  3. When you realize that running operation will never, ever be nested. 当你意识到永远不会嵌套运行操作时。

Handler : Handler

When we install an application in android, then it creates a thread for that application called MAIN UI Thread. 当我们在android中安装应用程序时,它会为该应用程序创建一个名为MAIN UI Thread的线程。 All activities run inside that thread. 所有活动都在该线程内运行。 By the android single thread model rule, we can not access UI elements (bitmap , textview etc..) directly for another thread defined inside that activity. 通过android单线程模型规则,我们无法直接访问该元素内部定义的另一个线程的UI元素(位图,textview等)。

A Handler allows you communicate back with the UI thread from other background thread. Handler允许您与其他后台线程的UI线程进行通信。 This is useful in android as android doesn't allow other threads to communicate directly with UI thread. 这在android中很有用,因为android不允许其他线程直接与UI线程通信。 Handler can send and process Message and Runnable objects associated with a thread's MessageQueue. 处理程序可以发送和处理与线程的MessageQueue关联的Message和Runnable对象。 Each Handler instance is associated with a single thread and that thread's message queue. 每个Handler实例都与一个线程和该线程的消息队列相关联。 When a new Handler is created, it is bound to the thread/message queue of the thread that is creating it. 创建新的Handler时,它将绑定到创建它的线程的线程/消息队列。

It's the best fit for: 它最适合:

  1. It allows you to do message queuing. 它允许您进行消息排队。
  2. Message scheduling. 消息调度。

Thread : Thread

Now it's time to talk about thread. 现在是讨论线程的时候了。

Thread is the parent of both AsyncTask and Handler . Thread是AsyncTaskHandler的父级。 They both internally use thread, which means you can also create your own thread model like AsyncTask and Handler , but that requires a good knowledge of Java's Multi-Threading Implementation . 它们都在内部使用线程,这意味着您也可以创建自己的线程模型,AsyncTaskHandler ,但这需要熟悉Java的多线程实现


#5楼

Let me try and answer the question here with an example :) - MyImageSearch [Kindly refer the image here of the main activity screen - containing an edit text / search button / grid view] 让我试着用一个例子回答这个问题:) - MyImageSearch [请参考主活动屏幕的图片 - 包含编辑文本/搜索按钮/网格视图]

MyImageSearch

Description of MyImageSearch - Once user enters the details on the edit text field and clicks on the search button, we will search images on the internet via the web services provided by flickr (you only need to register there to get a key/secret token) - for searching we send an HTTP Request and GET JSON Data back in response containing the url's of individual images which we will then use to load the grid view. MyImageSearch的描述 - 一旦用户输入编辑文本字段的详细信息并点击搜索按钮,我们将通过flickr提供的Web服务在互联网上搜索图像(您只需要在那里注册以获取密钥/秘密令牌) - 为了搜索,我们发送一个HTTP请求和GET JSON数据作为响应,包含我们将用于加载网格视图的各个图像的URL。

My Implementation - In the main activity I will define a inner class which extends the AsyncTask to send the HTTP Request in doInBackGround Method and fetch the JSON Response and update my local ArrayList of FlickrItems which I am going to use to update my GridView via the FlickrAdapter (extends the BaseAdapter) and call the adapter.notifyDataSetChanged() in the onPostExecute() of AsyncTask to reload the grid view. 我的实现 - 在主要活动中,我将定义一个内部类,它扩展AsyncTask以在doInBackGround方法中发送HTTP请求并获取JSON响应并更新我的FlickrItems的本地ArrayList,我将使用它通过FlickrAdapter更新我的GridView (扩展BaseAdapter)并调用AsyncTask的onPostExecute()中的adapter.notifyDataSetChanged()来重新加载网格视图。 Note that here the HTTP Request is a blocking call because of which I have done it via the AsyncTask. 请注意,这里的HTTP请求是一个阻塞调用,因为我通过AsyncTask完成了它。 And, I can cache the items in adapter to increase the performance or store them on SDCard. 而且,我可以将项目缓存在适配器中以提高性能或将它们存储在SDCard上。 The grid that I will be inflating in the FlickrAdapter contains in my implementation a progressbar and image view. 我将在FlickrAdapter中充气的网格在我的实现中包含进度条和图像视图。 Below you can find the code for mainActivity which I used. 您可以在下面找到我使用的mainActivity的代码。

Answer to the Question Now - So once we have the JSON data for fetching individual Images we can implement the logic of getting the images in background via Handlers or Threads or AsyncTask. 现在回答问题 - 所以一旦我们获得了用于获取单个图像的JSON数据,我们就可以实现通过处理程序或线程或AsyncTask在后台获取图像的逻辑。 We should note here that since my images once downloaded must be displayed on the UI/main thread we cannot simply use threads as it is since they don't have access to the context. 我们在此应该注意,由于我的图像一旦下载必须显示在UI /主线程上,我们不能简单地使用线程,因为它们无法访问上下文。 In the FlickrAdapter, the choices I could think of: 在FlickrAdapter中,我能想到的选择:

  • Choice 1: Create a LooperThread [extends thread] - and keep on downloading images sequentially in one thread by keeping this thread open [looper.loop()] 选择1:创建一个LooperThread [扩展线程] - 并通过保持此线程打开继续在一个线程中顺序下载图像[looper.loop()]
  • Choice 2: Make use of a Thread Pool and post the runnable via myHandler which contains reference to my ImageView, but since the views in Grid View are recycled, again the problem might arise where image at index 4 is displayed at index 9 [download may take more time] 选择2:使用线程池并通过myHandler发布runnable,其中包含对我的ImageView的引用,但由于Grid View中的视图被回收,因此可能会出现索引4处的图像显示在索引9处的问题[下载可能花更多的时间]
  • Choice 3 [I used this]: Make use of a Thread Pool and send a message to myHandler, which contains data related to ImageView's index and ImageView itself, so while doing handleMessage() we will update the ImageView only if currentIndex matches the index of the Image we tried to download. 选择3 [我用过]:使用线程池并向myHandler发送消息,其中包含与ImageView索引和ImageView本身相关的数据,因此在执行handleMessage()时,只有当currentIndex与索引匹配时才会更新ImageView。我们试图下载的图片。
  • Choice 4: Make use of AsyncTask to download the images in background, but here I will not have access to the number of threads I want in the thread pool and it varies with different android version, but in Choice 3 I can make of conscious decision of the size of thread pool depending on device configuration being used. 选择4:利用AsyncTask在后台下载图像,但是在这里我将无法访问线程池中我想要的线程数,并且它随着不同的Android版本而变化,但在选择3中我可以做出有意识的决定线程池大小取决于所使用的设备配置。

Here the source code: 这里的源代码:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

I hope my answer though long will help in understanding some of the finer details. 我希望我的答案虽然很长,但有助于理解一些更精细的细节。


#6楼

As the Tutorial on Android background processing with Handlers, AsyncTask and Loaders on the Vogella site puts it: 在Vogella网站上使用Handler,AsyncTask和Loaders进行Android背景处理教程时,可以看到:

The Handler class can be used to register to a thread and provides a simple channel to send data to this thread. Handler类可用于注册一个线程,并提供一个简单的通道来向该线程发送数据。

The AsyncTask class encapsulates the creation of a background process and the synchronization with the main thread. AsyncTask类封装了后台进程的创建以及与主线程的同步。 It also supports reporting progress of the running tasks. 它还支持报告正在运行的任务的进度。

And a Thread is basically the core element of multithreading which a developer can use with the following disadvantage: Thread基本上是多线程的核心元素,开发人员可以使用它具有以下缺点:

If you use Java threads you have to handle the following requirements in your own code: 如果使用Java线程,则必须在自己的代码中处理以下要求:

  • Synchronization with the main thread if you post back results to the user interface 如果将结果发布到用户界面,则与主线程同步
  • No default for canceling the thread 取消线程没有默认值
  • No default thread pooling 没有默认的线程池
  • No default for handling configuration changes in Android 在Android中处理配置更改没有默认值

And regarding the AsyncTask , as the Android Developer's Reference puts it: 关于AsyncTask ,正如Android Developer's Reference所说:

AsyncTask enables proper and easy use of the UI thread. AsyncTask可以正确,方便地使用UI线程。 This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers. 此类允许执行后台操作并在UI线程上发布结果,而无需操作线程和/或处理程序。

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTask旨在成为ThreadHandler的辅助类,并不构成通用的线程框架。 AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask. 理想情况下,AsyncTasks应该用于短操作(最多几秒钟。)如果需要保持线程长时间运行,强烈建议您使用java.util.concurrent包提供的各种API,例如Executor,ThreadPoolExecutor和FutureTask。

Update May 2015: I found an excellent series of lectures covering this topic. 2015年5月更新:我发现了一系列涵盖此主题的精彩课程

This is the Google Search: Douglas Schmidt lecture android concurrency and synchronisation 这是谷歌搜索: 道格拉斯施密特讲的android并发和同步

This is the video of the first lecture on YouTube 这是YouTube上第一次讲座的视频

All this is part of the CS 282 (2013): Systems Programming for Android from the Vanderbilt University . 所有这些都是CS 282(2013): 范德比尔特大学的 Android系统编程的一部分 Here's the YouTube Playlist 这是YouTube播放列表

Douglas Schmidt seems to be an excellent lecturer 道格拉斯施密特似乎是一位出色的讲师

Important: If you are at a point where you are considering to use AsyncTask to solve your threading issues, you should first check out ReactiveX/RxAndroid for a possibly more appropriate programming pattern. 重要提示:如果您正在考虑使用AsyncTask来解决线程问题,则应首先查看ReactiveX/RxAndroid以获得更合适的编程模式。 A very good resource for getting an overview is Learning RxJava 2 for Android by example . 获取概述的一个非常好的资源是通过示例学习RxJava 2 for Android

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值