我仍然对线程感到困惑。我仍然可以看到一些指向线程、UI 线程、后台线程、主线程等的答案(主要在 AsyncTasks 和从后台线程更新 UI 等)
谁能给我一个关于这些或至少一些链接的完整解释?
如果答案涵盖以下情况,那就太好了:
其中涉及的所有线程:
- 当我运行活动时(设置内容视图、附加一些按钮、一些对话框消息)
- 带有 AsyncTask 的活动
- 后台服务
- HTTP 调用
我仍然对线程感到困惑。我仍然可以看到一些指向线程、UI 线程、后台线程、主线程等的答案(主要在 AsyncTasks 和从后台线程更新 UI 等)
谁能给我一个关于这些或至少一些链接的完整解释?
如果答案涵盖以下情况,那就太好了:
其中涉及的所有线程:
后台服务(service)服务默认运行在与应用程序相同的进程中。在它自己的线程中。(正如@MisterSmith 所指出的)服务默认运行在与应用程序相同的进程中。在它自己的线程中。因此,您需要在服务中使用异步处理来在后台执行资源密集型任务。在应用程序进程中运行的服务有时称为本地服务。以为您可以指定在自己的进程中运行服务:
如果服务在其主线程中执行长时间运行的操作,则在其自己的进程中运行服务不会阻塞应用程序。但是由于服务在其自己的进程中运行,您需要使用一些进程间通信 (IPC) 从其他部分与您的服务进行通信。
HttpClient
(来自文档:HTTP 客户端的线程安全取决于特定客户端的实现和配置。
),必须通过使用在非 UI 线程上执行new Thread(new Runnable(...)).start();
,否则您将NetworkOnMainThreadException
感谢@vikram。但似乎该HttpClient.execute()
方法是在一个线程中执行的,这就是为什么它需要一个处理程序作为参数之一,以便将结果传递给相应的处理程序(处理程序在 UI 线程上运行并且可以按原样更新小部件(UI 元素)需要)
额外的:
要强制在主线程上执行某些操作,请使用yourContextInstance.runOnUiThread(new Runnable(....));
为了确定当前线程是否是 UI(main) 线程:
Looper.getMainLooper().getThread() == Thread.currentThread();
关于服务中线程的有趣问题:
为什么 UI 线程负责这一切?
因为 UI 线程负责将事件分派给适当的小部件(UI 元素),其中包括绘图事件
当我运行活动时(设置内容视图、附加一些按钮、一些对话框消息)
通常只有一个线程(主线程,有时被错误地称为 UI 线程)。
活动 - 带有异步任务
同样,默认情况下只有一个(主要的)。菜单和按钮处理程序也在主线程中运行。AsyncTask
是一个不同的故事。它创建了一个工作线程(顺便说一句,退出活动时您应该小心不要泄漏它)。
后台服务
服务默认在主线程中运行。广播接收器也是如此。这就是为什么主线程不是(仅)UI 线程的原因。不过,某些类型的服务(如流行的IntentService
)会产生一个工作线程。
一个 http 调用
是一个同步操作,所以它会阻塞直到它完成(这就是为什么你不应该在主线程中执行一个)。
Technically speaking an application can have as many threads as it wants, they are arbitrarily created by the programmer.
However, the standard android application by default has one thread. That is the main thread, and is often referred to as the UI thread (as it is the only thread with access to the UI). By default everything happens in the main thread.
If you run an async task, different parts run in different threads, here's a basic breakdown:
onPreExecute()
runs in the UI thread and is first called when you execute an async task.
doInBackground()
runs in a newly spawned thread separate from the main/UI thread.
onPostExecute()
runs in the UI thread after the background task returns.
A background service runs entirely separately from the application, it can run indefinitely even if the original application is destroyed.
An http call happens on whatever thread you call it on, but as a requirement of newer android API's you can no longer do any network activity from the main/UI thread. (This will actually cause an exception and terminate your application) This is to prevent slow network calls from blocking the main thread and therefore creating a choppy user experience.
其中涉及的所有线程:
当我运行活动时(设置内容视图、附加一些按钮、一些对话框消息)
此处涉及 UI 线程或主线程。
带有 AsyncTask 的活动
UI Thread 和 WorkerThread 都参与其中。
AsyncTask允许正确和轻松地使用 UI 线程。此类允许您在 UI 线程上执行后台操作并发布结果,而无需操作线程和/或处理程序。
4个步骤
当一个异步任务被执行时,任务会经过 4 个步骤:
onPreExecute()
,在执行任务之前在 UI 线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。
doInBackground(Params...)
onPreExecute()
,在完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。此步骤还可publishProgress(Progress...)
用于发布一个或多个进度单位。这些值在onProgressUpdate(Progress...)
步骤中的 UI 线程上发布。
onProgressUpdate
(进度...),在调用publishProgress(Progress...)
. 此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。
onPostExecute
(结果),在后台计算完成后在 UI 线程上调用。后台计算的结果作为参数传递给该步骤。
后台服务
IntentService类为在单个后台线程上运行操作提供了一个简单的结构。这允许它处理长时间运行的操作而不影响用户界面的响应
HTTP 调用
无法从 UI 线程(或 MainThread)执行 NetwokrkOperation。因此,请使用AsyncTask或HandlerThread 之类的替代方案
相关文章: