Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 常见的建议是什么;在服务中启动一个线程;什么意思?_Java_Android_Multithreading_Service - Fatal编程技术网

Java 常见的建议是什么;在服务中启动一个线程;什么意思?

Java 常见的建议是什么;在服务中启动一个线程;什么意思?,java,android,multithreading,service,Java,Android,Multithreading,Service,服务回调与活动一样在主线程上运行(除非另有规定)。我似乎在这里偶然发现了很多建议,比如“在服务中启动一个线程[在后台工作]”。这对我来说没有意义。只要应用程序进程中存在已启动的服务组件,从活动代码启动线程与从服务代码启动线程相比有什么关系 如果答案是我所想的(这无关紧要),那么令人遗憾的是,人们给人的印象是,一个服务对象需要以某种方式与背景线程相关。当涉及到服务时,“背景”一词可能会产生误导,因为它可能有两种含义服务用于运行任务,简单地说就是,即使应用程序没有运行的活动。要澄清这一点,请考虑一个

服务回调与活动一样在主线程上运行(除非另有规定)。我似乎在这里偶然发现了很多建议,比如“在服务中启动一个线程[在后台工作]”。这对我来说没有意义。只要应用程序进程中存在已启动的服务组件,从活动代码启动线程与从服务代码启动线程相比有什么关系

如果答案是我所想的(这无关紧要),那么令人遗憾的是,人们给人的印象是,一个服务对象需要以某种方式与背景线程相关。

当涉及到
服务时,“背景”一词可能会产生误导,因为它可能有两种含义<代码>服务
用于运行任务,简单地说就是,即使应用程序没有运行的
活动
。要澄清这一点,请考虑一个音乐播放器;您希望即使
活动
未运行,音乐仍能播放。这是背景的定义,与
线程无关;您正在后台运行应用程序的一部分,因为您的应用程序在屏幕上没有任何可见组件(可能有一些
通知
,但没有全屏UI)


现在,假设您想从internet下载一些数据。您可能知道,您无法在UI
线程中执行长时间运行的任务(从API 11+开始,您将获得一个
NetworkMainThreadException
),因此您需要使用后台
线程。假设您不想使用
AsyncTask
下载内容,因为
服务更适合您的需要。在这种情况下,您必须在后台
线程
上启动
服务
。这是background的第二个含义,它基本上意味着创建一个新的
线程。Android提供了一个类来实现这一点<代码>意向服务
。它是一项在后台
线程上运行的
服务
,当给定任务完成时,它会自动完成。

如果线程的生命周期通过应用程序进程状态反映出来,那么实际上在何处启动线程并不重要:

Android不在乎是否有
线程运行。即使你的应用程序被认为是一个“不包含任何活动应用程序组件”的空进程,线程也会运行。不要滥用它,因为用户不希望应用程序在看起来死气沉沉的情况下仍处于秘密活动状态

如果你想(而且你应该)安卓不会随意杀死你,尽管你的线程还没有完成,你必须确保你保持一个例如
服务
处于启动状态

服务
(或仅使用
IntentService
)中创建线程将主要产生更好、更简单和更干净的代码。例如,因为
服务
有一个
上下文
,您不能从那里泄露
活动
。您还可以从系统获得免费回调

通过螺纹的泄漏非常容易

new Thread(new Runnable() {
    @Override
    public void run() {
        SystemClock.sleep(Long.MAX_VALUE);
    }
}).start();
如果您只是将活动放入例如
onCreate
中,则会泄漏活动,因为匿名内部
Runnable
保留了对
活动的引用,并且在线程停止运行并且自身被垃圾收集之前不会释放它


如果您真的知道自己在做什么,可以随意启动活动中的线程,并手动将其生命周期同步到一些空的
服务
。我不推荐这样做,因为要正确地做到这一点,不太可能需要更少的工作。

感谢您的回答和努力。我同意你直到“你必须在后台线程上启动服务”。我为什么要这么做?这能实现什么?据我所知,启动服务并不昂贵,而且可以在主线程上轻松完成,而不会对响应性造成任何影响。我也看不到文档中有什么地方说,
IntentService
回调在与主线程不同的线程中运行,如果它是从那里开始的。唯一显而易见的是,它的
onHandleIntent()
将在另一个线程上调用。长时间运行的任务必须在单独的
线程上运行。例如,您真的不知道网络呼叫需要多长时间,因此如果您没有在后台
线程
上运行它,UI将一直没有响应。绑定一个
IntentService
可能不是一个好主意,因此没有回调。您可能应该使用
LocalBroadcastManager
将结果传递给应用程序的其余部分。通过这种方式,您的
服务
与您的
活动
尽可能松散地耦合在一起,我认为我们谈论的是完全不同的事情。我对辅助线程的用例不感兴趣。我感兴趣的是,在我的代码中,线程从何处开始是否重要。我对此很感兴趣,因为在其他答案中暗示“您应该在服务中启动一个线程”。这与“你应该启动一项服务,然后[从任何地方]创建一个新的线程”形成对比。你能提供一个链接来回答这个问题吗?您可以从需要的位置启动
线程
。无需在
服务上启动它
当然,这里有一个。我经常看到它,并认为它可能有一些东西。
Handler
Looper
与线程交互的隐蔽方式让我怀疑自己对幕后发生的事情的了解,因为我是Android新手(但不是Java)。如果没有给出反对票的理由,那么我的下一个问题可能就是这个。这非常有帮助,你消除了我的疑虑。您还添加了一些隐藏的陷阱,即不按建议的方式进行操作,这正是