首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >我如何才能运行一个服务,该服务可以访问我的数据库并对其运行操作,但不会填满UI线程

我如何才能运行一个服务,该服务可以访问我的数据库并对其运行操作,但不会填满UI线程
EN

Stack Overflow用户
提问于 2019-11-14 05:48:29
回答 1查看 102关注 0票数 0

我正在构建一个应用程序,需要检查存储在本地的照片集合,我将这些照片导入到房间数据库中,并尝试检测每个照片是否包含人脸。我已经解决了所有的问题,我唯一的问题是如何在一个不会填满UI线程的服务中运行这个操作,这可能需要一段时间。

起初,我想使用JobIntentService,但不能使用,因为我不能在后台线程上使用observeForever,也不能使用简单的观察者,因为我没有lifecycleOwner可以提供给Observer

我最终只使用了一个服务,一旦操作开始,我的UI就被卡住了,如果我试图做任何事情,应用程序就会崩溃。

我尝试过IntentService,但我不能在onHandleIntent中使用观察者,因为它是一个工作线程,它不允许我使用,当我在onStartCommand下运行操作时,它也是一样的。

我觉得我被这个东西的架构卡住了,我很感激任何想法。谢谢。

这是我的服务:

代码语言:javascript
运行
AI代码解释
复制
class DetectJobIntentService : Service() {

    private val TAG = "DetectJobIntentServi22"
    lateinit var repo: PhotoRepository
    lateinit var observer : Observer<MutableList<Photo>>

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        val options = FirebaseVisionFaceDetectorOptions.Builder()
            .setClassificationMode(FirebaseVisionFaceDetectorOptions.ACCURATE)
            .setClassificationMode(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
            .setMinFaceSize(0.15f)
            .build()

        val detector = FirebaseVision.getInstance()
            .getVisionFaceDetector(options)

        repo = PhotoRepository(application)

        observer = Observer {
            for (file in it) {
                val image = FirebaseVisionImage.fromFilePath(application, Uri.parse(file.uri))
                AsyncTask.execute {
                    detector.detectInImage(image).addOnSuccessListener { list ->
                        if (list.isNotEmpty()) {
                            file.hasFaces = 1
                            repo.update(file)
                        } else {
                            file.hasFaces = 2
                            repo.update(file)
                        }
                    }
                }


            }
        }

        repo.getAllPhotos().observeForever(observer)

        val notificationIntent= Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(this,
            0, notificationIntent, 0)

        val notification = NotificationCompat.Builder(this, getString(tech.levanter.anyvision.R.string.channel_id))
            .setContentTitle("Detecting faces..")
            .setContentText("64 photos detected")
            .setSmallIcon(tech.levanter.anyvision.R.drawable.ic_face)
            .setContentIntent(pendingIntent)
            .build()

        startForeground(1, notification)

        return START_NOT_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        repo.getAllPhotos().removeObserver(observer)
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-14 06:16:17

既然你的代码是用Kotlin编写的,我建议你试试Kotlin Coroutines。这将使您能够分派昂贵的操作,例如查询数据库,向其他线程发出网络请求/调用,从而不会阻塞UIThreadCoroutines可以帮助您避免callbacks带来的麻烦。此外,谷歌刚刚弃用了AsyncTask应用程序接口,转而支持Coroutines作为多线程的方式。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58850155

复制
相关文章

相似问题

领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文