为啥不在主线程(Android)中完成所有操作? [关闭]

Posted

技术标签:

【中文标题】为啥不在主线程(Android)中完成所有操作? [关闭]【英文标题】:Why not do all the operations in the main thread(Android)? [closed]为什么不在主线程(Android)中完成所有操作? [关闭] 【发布时间】:2014-08-11 21:43:09 【问题描述】:

这是一个关于 AsyncTask 类的澄清问题,以及使用该类进行网络操作(抓取数据)的具体示例。

在 doInBackground 操作之后同步运行的 onPostExecute 方法与让主线程完成所有工作(onPostExecute 和 doInBackground)有何不同?

该主线程将按顺序执行这些操作,获取网络数据,然后在 onPostExecute 中执行工作。

【问题讨论】:

看看这个 --> vogella.com/tutorials/androidBackgroundProcessing/article.html 这个问题的问题在于它太宽泛,根本没有重点。我无法为此重新打开它,但我可以建议您举一个使用 onPostExecute 方法的具体示例,但您不理解它。抱歉,我无法为您提供更多帮助 @aradhna 感谢您的文章!该文章中的这句话本身回答了这个问题 - “如果您执行长期操作,例如从 Internet 访问数据,应用程序会阻塞,直到相应的操作完成。” 【参考方案1】:

来自docs:

当启动应用程序时,系统会为应用程序创建一个执行线程,称为“main”。这个线程非常重要,因为它负责将事件分派给适当的用户界面小部件,包括绘图事件。

也就是说,所有 UI相关的任务都发生在同一个线程上,称为主线程或UI线程。

当您的应用执行大量工作以响应用户交互时,除非您正确实施应用,否则这种单线程模型可能会产生较差的性能。具体来说,如果一切都发生在 UI 线程中,那么执行网络访问或数据库查询等长时间操作将阻塞整个 UI。

简单地说,当 UI 必须等待某些 I/O、数据检索或数据处理完成才能完成屏幕渲染时,您的应用程序会“挂起”直到该过程完成。

如果他们不满意,用户可能会决定退出您的应用程序并卸载它。

我认为这是不言自明的。

Android 的单线程模型只有两条规则:

    不要阻塞 UI 线程 不要从 UI 线程外部访问 Android UI 工具包

因此,与 UI 无关的所有内容必须在单独的线程中完成,而与 UI 相关的所有内容必须没有的情况下完成任何类型的并行处理。

那么我们如何进行并行处理呢? Android 根据您的需要提供不同类型的并行处理:

1. 好旧的 Java Threads

2. Handlers

3. Activity.runOnUiThread(Runnable)

4. View.post(Runnable)

5. View.postDelayed(Runnable, long)

6. AsyncTasks

7. IntentServicesServices 请勿在单独的线程上运行)。

附带说明,Android 特别强制所有网络操作在单独的线程上执行,否则会抛出 NetworkOnMainThreadException

现在回到你的问题:

我的问题是这种差异形式如何仅在主线程上运行所有内容?我知道 onPostExecute 必须等待后台检索中的 xml 完成,这仍会为用户锁定 ui?

如果设备有多个内核,UI 渲染将通过一个内核(主线程)完成,而 doInBackground() 方法在另一个内核(AsyncTask 线程)上执行,并且onPostExecute() 方法仅在 doInBackground() 返回后才在主线程上调用。这意味着 onPostExecute() 也在等待 UI 完成渲染,因为 UI 渲染和 onPostExecute() 都发生在主线程上。

现在如果设备只有一个核心,一切都将发生在一个核心上,但doInBackground() 将在单独的线程上执行,并且onPostExecute() 将仅在 UI 渲染完成并且doInBackground() 完成后调用返回。

我希望这会有所帮助。

进一步阅读:

1. Understanding AsyncTask – Once and Forever

2. Is Android’s AsyncTask executing tasks serially or concurrently?

【讨论】:

对不起,我应该更清楚...术语“核心”是指设备微处理器中的 CPU 数量。过去微处理器是单核的,传统上一个核一次可以执行一条指令,也就是说一个核处理一个线程,上下文切换造成了多任务的错觉.单个处理器中存在多个内核是真正在计算机(现在也包括移动设备!)中实现多任务处理的原因......这有帮助吗? 设备是否有微处理器和主处理器(CPU?) 两者指的是同一个东西【参考方案2】:

这与效率无关:网络 I/O 在主线程中明确禁止(至少从 Android 3.0 开始)。因此,有必要通过某种方式将这些任务卸载到后台线程中。

AsyncTask 只是实现这一点的一种非常方便的机制。

见How to fix android.os.NetworkOnMainThreadException?

【讨论】:

【参考方案3】:

这很简单。如果你在主线程上下载你的东西,它会阻塞你的 UI 并且ANR dialog 会出现。您的 Activity 与 XML 相关联:

 setContentView(R.layout.activity_main);

但是如果你使用 Asynctask 会启动新线程,这与 UI 无关。所以在你开始你的异步任务之后,你仍然可以显示任何你想要的东西,按钮将是可点击的,等等。如果你将它下载到你的主线程上,用户可以认为应用程序冻结并退出,尽管它只是在做一些计算。

【讨论】:

以上是关于为啥不在主线程(Android)中完成所有操作? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UIWebView 的 AVPlayerViewController 不在主线程上运行?

为啥不在构造函数中启动一个线程?如何终止?

『进阶之路』—— 线程池

Android中是否新开一个activity就是新建了一个线程

为啥要在主线程操作UI

Android SDK使用HttpClient的问题,为啥老是报错,困扰了我好几天,求大神解救!