我如何运行可以访问我的数据库并可以在其上运行操 作,但不会填满UI线程的服务

问题描述 投票:0回答:1

我正在构建一个应用,需要浏览一系列本地存储的照片,然后将其导入到房间数据库中,并尝试检测每个照片是否包含面部。我已经完成了所有排序工作,唯一的问题是如何在不会​​塞满UI线程的服务中运行此操作,这可能需要一段时间。

起初我想使用JobIntentService,但是不能,因为我无法在后台线程上观察Forever,并且因为我没有lifecycleOwner提供给Observer,所以无法使用简单的观察器。

我最终只使用了一项服务,操作开始后,我的UI几乎卡住了,如果我尝试做任何事情,应用程序就会崩溃。

我尝试过IntentService,但是我不能在onHandleIntent中使用观察器,因为它是一个工作线程,并且不允许我使用,而当我在onStartCommand下运行操作时,则是同一件事。

我感觉自己对这个东西的体系结构感到困惑,我很感激任何想法。谢谢。

这是我的服务:

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)
    }

}

我正在构建一个应用,需要浏览一系列本地存储的照片,然后将其导入到房间数据库中,并尝试检测每个照片是否包含面部。我什么都有...

android multithreading service architecture android-architecture-components
1个回答
0
投票

[看到您的代码在Kotlin中,我建议您尝试Kotlin Coroutines。这将使您能够分派昂贵的操作,即查询数据库,对其他线程进行网络请求/调用,从而不会阻塞UIThreadCoroutines帮助您避免callbacks的麻烦。此外,Google不再推荐使用AsyncTask API,而推荐使用Coroutines作为多线程用途。

© www.soinside.com 2019 - 2024. All rights reserved.