【问题标题】:Android/Java decisions about threading关于线程的 Android/Java 决策
【发布时间】:2014-10-09 14:44:50
【问题描述】:

好的,所以在玩了一点 Android SDK 之后,我决定开发一个完整的应用程序。不一定要在商店发布(我真的没有可用的工具来进行适当的质量检查,所以感觉不对;我只能在我的一台个人设备上进行测试)它主要只是一个个人项目,用于娱乐和学习。最后,我决定使用相机应用程序,因为我经常使用我的相机,所以如果我制作它,我最终会实际使用这种应用程序,而且我对新的 Camera2 API 的功能感到非常兴奋Android L 并想试一试。

无论如何,我一直在思考应用程序的设计/架构,但我遇到了一个我无法真正解决的潜在问题,因为我不仅不熟悉这种性质的 GUI 编程,而且在 Java 和 Android SDK 上不是 100%。他们都坐在我日常工作的范围之外。

现在我知道我确实需要将我的 UI 线程与其他所有线程分开,但我不确定首先,我应该将额外线程用于什么(我正在考虑一个处理图像捕获和存储的线程) , 和另一个来处理设置?也许这已经结束了)以及是否拥有 UI 线程通过事件与之通信的后台线程,或者只是在需要时生成线程。也许是一个在 UI 线程和任何需要完成的后台处理之间进行仲裁的中间后台线程?我的意思是,我如何决定这些事情?是否有一般/最佳实践?

我真的在问,因为我想正确完成这项工作并事先彻底计划应用程序,因为过去我发现如果我直接投入,我很容易感到困惑并最终失去信心并放弃项目。我希望有人能帮忙。我发现这不是一个容易用 Google 提供令人满意的结果的方式表达的问题。

【问题讨论】:

    标签: java android multithreading user-interface


    【解决方案1】:

    在图像捕获方面,您无需担心线程。当您想拍照时,您可以打开设备上的相机应用程序。 Here 是这样做的好方法。

    Android SDK 提供Asynctask,它会在后台线程中为您做一些事情,例如网络调用,并在完成后更新 UI。

    您还可以使用IntentService,即使您退出应用程序并执行上传/下载等操作,用户也不必担心它会运行。 Loaders 在底层数据经常变化并且您需要快速更新 UI(例如在自动完成文本中搜索联系人)时很有用。

    http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html

    请参阅本教程,这是一个好的开始。希望这会有所帮助。

    【讨论】:

    • 哎呀!不不不!服务在 UI 线程上运行! ...而且,FWIW,Loader 是一个 AsyncTask。
    • 嗯,是的,加载器在内部使用 AsyncTask,但加载器在某些情况下更好,了解所有选项很高兴。
    • A Service 通常在应用程序的主线程上运行,但可以在清单中设置它在自己的进程中运行,在这种情况下它将拥有自己的自己的主线程。
    • 感谢您的链接,虽然使用相机应用程序拍照并不是我想要的。我希望使用带有我自己设计的 UI 的 Camera2 API 开发我自己的应用程序...
    【解决方案2】:

    我想你可以考虑这样考虑:

    UI 线程是大多数东西运行的地方。它有时也被称为“主”线程,因为它是,呃……主线程。

    除非您的程序非常复杂,否则您可能不需要担心线程架构。您需要担心的只是让 UI 线程关闭缓慢的东西。而已。你不关心他们去哪里,只是不关心 UI 线程。

    如果你买了,有一些不错的选择:

    1. Intent 服务:打个比方,如果您需要在“后台”运行的方法具有 void 返回类型,那么 Intent 服务就是完美的解决方案。您使用 Intent 与它进行通信,并且由于它只有一个线程,因此您提交给该线程的任务会按顺序运行。
    2. AsyncTask:这些都充满了问题,但人们用它们完成了很多编程。它们在大约 6 个线程的池中运行,但(令人惊讶!)无论如何都按顺序运行。
    3. 您自己的 Java Executor:如果您需要类似于 AsyncTask 的行为,但需要更多控制,请使用此功能。
    4. 每个任务的新线程:不要这样做。真的。

    但是,在任何这些情况下,您并不真正关心您的任务正在运行哪些线程。你制定一个关于目标设备上有意义的线程数量的策略,然后在其中一个设备上运行你的慢的东西。

    ...而“慢”应包括所有 I/O:数据库、文件系统、网络等,以及主要计算。

    【讨论】:

    • AsyncTask 在最新版本的 Android 中以单线程串行运行,除非另有说明。
    • @svenoaks:不是真的!它们在 Executor 上运行,线程池大小约为 6。然而,在 Executor 前面,有一个强制按顺序执行的出队。
    • 哦,你是对的,尽管文档特别说它在单个线程上执行(从用户的角度来看是这样),但来源的说法不同。
    • 是的。当您从 AsyncTask 运行代码时,问题就来了。该代码必须是线程安全的,因为不能保证它总是在同一个线程上运行(如果它按照文档描述的那样工作,就会有)
    • 你是对的。我想我想多了。我对其他答案感到满意,但我会接受这一点,因为它在解释我的选择方面似乎是最彻底的。谢谢!
    【解决方案3】:

    你想让事情尽可能简单。您不需要线程来设置设置,也不需要中间线程。这些事情只会造成不必要的复杂化。您只需要从 UI 线程中移除长时间运行的操作。

    首先看一下 Android 框架提供的结构,以使多线程更容易。这将有助于简化您的应用程序。这些将包括IntentServiceAsyncTask。如果这些不能满足您的需求,请查看java.util.concurrent 包。通常不建议使用原始线程。

    另一个可以派上用场的库是Event Bus like Otto。这将防止使用 AsyncTask 时可能发生的内存泄漏。

    【讨论】:

    • 谢谢,我一直在想太多事情......当我只是思考和思考而从不做的时候,我倾向于这样做。感谢您的链接,它们应该会派上用场!
    猜你喜欢
    • 2011-09-10
    • 2020-08-11
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 2019-03-08
    • 1970-01-01
    相关资源
    最近更新 更多