android-如何在与主线程不同的线程中运行服务?

Posted

技术标签:

【中文标题】android-如何在与主线程不同的线程中运行服务?【英文标题】:android-How to run Service in different thread than main thread? 【发布时间】:2013-11-02 14:50:43 【问题描述】:

我正在尝试在 android 中开发一个应用程序,该应用程序包含一个读取传感器值多个小时的服务。当我启动服务时,我的设备挂起,所有其他进程都变慢了。为了解决这个问题,我尝试在单独的线程中启动服务,如下所示,但问题仍然存在。

    new Thread(new Runnable() 

                @Override
                public void run() 
                    Intent intent=new Intent(getApplicationContext(), SensorService.class);
                    startService(intent);

                
            ).start();

这个线程只在不同的线程中启动服务,但服务在主线程中运行。 请有人帮助我如何在单独的线程中运行服务?

【问题讨论】:

您应该发布您尝试运行的代码,以便我们可以准确地看到您在做什么。我的猜测是您在服务中拥有的代码应该在新线程上执行。请发布您尝试执行的服务。 【参考方案1】:

应用程序组件(服务、活动等)始终在主线程中运行,无论它们是从哪个线程启动的。 请考虑在您的服务中启动线程,或使用IntentService

在您的特定情况下,您可能会尝试为传感器更改注册一个全局 BroadcastReceiver,这反过来又会启动一个 IntentService 以将新获取的值放入 db 等中。

其实here is the link类似的问题已经解决了。

同样,这并不是真正的多线程问题。整个任务必须以另一种方式实现。

【讨论】:

嗨尤金,感谢您的快速回复。传感器值每 70 毫秒变化一次,所以我认为我们不需要注册一个全球广播接收器。 恐怕长时间运行的任务在 70 毫秒注册事件会很快耗尽电池。 IntentService 现已弃用【参考方案2】:

您可以使用后台服务来解决这个问题。通过在特定情况下使用Threadsleep() 可以解决您的问题

Background Servies

这个链接会帮助你..

或者使用PendingIntent 会帮助你,比如...

PendingIntent operation = PendingIntent.getActivity(getBaseContext(), 0, ij, Intent.FLAG_ACTIVITY_NEW_TASK);

【讨论】:

【参考方案3】:

您所做的只是启动新活动,因此如果您运行监视器的逻辑位于SensorService 中,那么它仍将位于主线程上。您需要将监控逻辑放入新线程中,而不仅仅是使用它启动活动。

如果您尝试在后台线程上运行服务,则需要使用静态 performOnBackgrounThread 方法,如可在 Android 文档 (android-8\SampleSyncAdapter\src\com\example\android \samplesync\client\NetworkUtilities.java):

public static Thread performOnBackgroundThread(final Runnable runnable) 
    final Thread t = new Thread() 
        @Override
        public void run() 
            try 
                runnable.run();
             finally 

            
        
    ;
    t.start();
    return t;

同样重要的是要记住,您永远不想在主 UI 线程上执行网络操作。不是你在这里,只是一个仅供参考......

【讨论】:

嗨 Blaine,如何将监控逻辑放在新线程中。? 您提供的代码不起作用.. 服务仍在主线程中运行。我想在不同的线程中运行.. 您应该发布您尝试运行的代码,以便我们可以准确地看到您在做什么。【参考方案4】:

我认为这个问题的答案在于IntentService 的力量。 IntentService 是常规 Service 类的子类。但是,有一些关键的区别。

现在,您可以通过以下方式利用 IntentServices:IntentServices 不在主线程上运行。相反,它们在单独的“工作线程”上运行。这个单一属性将解决您的问题并消除您当前面临的 ANR。

要详细了解服务和 IntentServices 之间的区别,check this out。

【讨论】:

【参考方案5】:

您可以尝试使用AsyncTask,请阅读此文档。

http://developer.android.com/reference/android/os/AsyncTask.html

【讨论】:

这对我不起作用;尽管对 startService 的调用是在不同的线程中完成的,但该服务似乎仍在主线程中运行。【参考方案6】:

要在同一个进程但另一个非主线程中启动服务,我们可以创建另一个HandlerThread 并使用Handler 在其上运行我们的作业。

class MyService : Service() 
    private lateinit var thread: HandlerThread
    private lateinit var handler: Handler

    override fun onCreate() 
        super.onCreate()
        thread = HandlerThread("MyService").apply 
            start()
        
        handler = Handler(thread.looper)
    

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int 
        if (intent?.action == "my-job") 
            handler.post 
                // Do any job on another non-main thread here
                // ...
            
        
    

    override fun onDestroy() 
        thread.interrupt()
        super.onDestroy()
    

【讨论】:

以上是关于android-如何在与主线程不同的线程中运行服务?的主要内容,如果未能解决你的问题,请参考以下文章

调用不切换回单独的线程

Android Handler 异步调用修改界面与主线程

怎么使用Web Workers提升性能?

使用 Flask 运行计划时的问题

eclipse中做android游戏如何创建Thread(线程)

如何找到线程正在运行的处理器编号?