Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.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
Android 如何使用Kotlin协同程序有效地从任何音乐文件中提取唱片集艺术_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Android 如何使用Kotlin协同程序有效地从任何音乐文件中提取唱片集艺术

Android 如何使用Kotlin协同程序有效地从任何音乐文件中提取唱片集艺术,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,在我的应用程序中,我试图从手机存储器中的所有音乐文件中提取唱片集艺术,然后将它们填充到我的RecyclerView中。我成功地获取了所有内容,但所有曲目都需要花费大量时间才能渲染到我的RecyclerView。我想做的就是,只要我的应用程序启动,所有曲目都应该立即在RecyclerView中填入合适的专辑艺术,没有任何延迟。我试图将我的代码放入协同程序中,但仍然需要大量的延迟。任何帮助都将不胜感激 fun getSongList() = GlobalScope.launch(Dispatcher

在我的应用程序中,我试图从手机存储器中的所有音乐文件中提取唱片集艺术,然后将它们填充到我的
RecyclerView
中。我成功地获取了所有内容,但所有曲目都需要花费大量时间才能渲染到我的
RecyclerView
。我想做的就是,只要我的应用程序启动,所有曲目都应该立即在
RecyclerView
中填入合适的专辑艺术,没有任何延迟。我试图将我的代码放入协同程序中,但仍然需要大量的延迟。任何帮助都将不胜感激

fun getSongList() = GlobalScope.launch(Dispatchers.IO)
    {
        async {
         realm = Realm.getDefaultInstance()
        val iterator = FileUtils.iterateFiles(
                Environment.getExternalStorageDirectory(),
                FileFilterUtils.suffixFileFilter("m4a"),
                TrueFileFilter.INSTANCE)
        while (iterator.hasNext()) {
            try {
                val fileINeed = iterator.next()
                val thisurls = fileINeed.canonicalPath
                val mmr = MediaMetadataRetriever()
                mmr.setDataSource(thisurls)
                var thisTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
                var thisArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                if (thisTitle.isNullOrEmpty()) {
                    thisTitle = fileINeed.name
                }
                if (thisArtist.isNullOrEmpty()) {
                    thisArtist = "Unknown Artist"
                }
                val query = realm!!.where(Songdetails::class.java).equalTo("songname",thisTitle).findFirst()
                if(query == null)
                {
                    val retriever = MediaMetadataRetriever()
                    retriever.setDataSource(thisurls)
                    val art = retriever.embeddedPicture
                    if (art != null) {
                        var bitmap = BitmapFactory.decodeByteArray(art, 0, art.size)
                        ImageSaver(MainActivity.getInstance()!!)
                                .setFileName(thisTitle)
                                .setDirectoryName("images")
                                .save(bitmap)
                         realm = Realm.getDefaultInstance()
                        realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = thisTitle
                                EventBus.getDefault().post("update")
                            }
                        })
                    }
                    else{
                         realm = Realm.getDefaultInstance()
                        realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = "custom"
                                EventBus.getDefault().post("update")
                            }
                        })
                    }
                }
            }catch (ex:Exception)
            {

            }
        }
         realm = Realm.getDefaultInstance()
        val mp3iterator = FileUtils.iterateFiles(
                Environment.getExternalStorageDirectory(),
                FileFilterUtils.suffixFileFilter("mp3"),
                TrueFileFilter.INSTANCE)
        while (mp3iterator.hasNext()) {
            try {
                val fileINeed = mp3iterator.next()
                val thisurls = fileINeed.canonicalPath
                val mmr = MediaMetadataRetriever()
                mmr.setDataSource(thisurls)
                var thisTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
                var thisArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                if (!thisTitle.isNullOrEmpty()) {
                    val query = realm!!.where(Songdetails::class.java).equalTo("songname", thisTitle).findFirst()
                    if (query == null) {
                        val retriever = MediaMetadataRetriever()
                        retriever.setDataSource(thisurls)
                        val art = retriever.embeddedPicture
                        if (art != null) {
                            var bitmap = BitmapFactory.decodeByteArray(art, 0, art.size)
                            ImageSaver(MainActivity.getInstance()!!)
                                    .setFileName(thisTitle)
                                    .setDirectoryName("images")
                                    .save(bitmap)
                            realm = Realm.getDefaultInstance()
                           realm!!.executeTransaction(object : Realm.Transaction {

                                override fun execute(realm: Realm) {
                                    // increment index
                                    var num = realm.where(Songdetails::class.java).max("id")
                                    var nextID: Int
                                    if (num == null) {
                                        nextID = 1
                                    } else {
                                        nextID = num.toInt() + 1
                                    }
                                    var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                    songitem.songname = thisTitle
                                    songitem.songartist = thisArtist
                                    songitem.songurl = thisurls
                                    songitem.songimage = thisTitle
                                    EventBus.getDefault().post("update")
                                }
                            })
                        }
                        else{
                             realm = Realm.getDefaultInstance()
                           realm!!.executeTransaction(object : Realm.Transaction {

                                override fun execute(realm: Realm) {
                                    // increment index
                                    var num = realm.where(Songdetails::class.java).max("id")
                                    var nextID: Int
                                    if (num == null) {
                                        nextID = 1
                                    } else {
                                        nextID = num.toInt() + 1
                                    }
                                    var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                    songitem.songname = thisTitle
                                    songitem.songartist = thisArtist
                                    songitem.songurl = thisurls
                                    songitem.songimage = "custom"
                                    EventBus.getDefault().post("update")
                                }
                            })
                        }
                    }

                }
            }catch (ex:Exception)
            {

            }
        }
        realm = Realm.getDefaultInstance()
        val waviterator = FileUtils.iterateFiles(
                Environment.getExternalStorageDirectory(),
                FileFilterUtils.suffixFileFilter("wav"),
                TrueFileFilter.INSTANCE)
        while (waviterator.hasNext()) {
            try {
                val fileINeed = waviterator.next()
                val thisurls = fileINeed.canonicalPath
                val mmr = MediaMetadataRetriever()
                mmr.setDataSource(thisurls)
                var thisTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
                var thisArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                if (thisTitle.isNullOrEmpty()) {
                    thisTitle = fileINeed.name
                }
                if (thisArtist.isNullOrEmpty()) {
                    thisArtist = "Unknown Artist"
                }
                val query = realm!!.where(Songdetails::class.java).equalTo("songname", thisTitle).findFirst()
                if (query == null) {
                    val retriever = MediaMetadataRetriever()
                    retriever.setDataSource(thisurls)
                    val art = retriever.embeddedPicture
                    if (art != null) {
                        var bitmap = BitmapFactory.decodeByteArray(art, 0, art.size)
                        ImageSaver(MainActivity.getInstance()!!)
                                .setFileName(thisTitle)
                                .setDirectoryName("images")
                                .save(bitmap)
                         realm = Realm.getDefaultInstance()
                       realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = thisTitle
                                EventBus.getDefault().post("update")
                            }
                        })
                    } else {
                         realm = Realm.getDefaultInstance()
                        realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = "custom"
                                EventBus.getDefault().post("update")
                            }
                        })
                    }

                }

            } catch (ex: Exception) {

            }
        }
        }
}

我只能猜测这是因为:

  • 您似乎正在读取媒体文件…获取图像位图,然后将图像保存在“/images”中。这真的需要相当多的时间…特别是如果你有很多文件要处理的话
  • 我看不到任何多线程?也许一个线程池可以帮助加快速度?我还没有用过合作程序,所以我可能错了
  • 这是在主/UI线程上运行的吗

  • 难道不可能只获取媒体文件列表,然后在
    RecyclerAdapter
    中在
    onBindViewHolder()
    中提取位图,而不是在应用程序启动时尝试全部操作,只将位图保留在RAM中,而不必麻烦持久保存到“/图像”中吗?

    您可以利用Coil或毕加索更好地缓存位图,以备后续发布。由于各种变量(曲目数量、图像曲目大小等),无论使用何种方法,最初的一张专辑都会花费一些时间。

    为什么不加载系统已生成的相册艺术?它将返回相册艺术的uri,然后您可以使用Glide/Picasso/Coil将其加载到imageview中。这应该比手动操作要快。

    是的,在我的手机中大约有200到300首音乐,在运行时渲染它们需要花费大量时间!您也可以建议使用其他方法来解决此问题。这不仅仅是获取图像位图的情况,即使获取整个音乐文件列表也不会立即发生。即使我在没有图像的情况下获取它们,也会花费很多时间。在主ui线程上运行任何操作所有文件获取都是在后台线程中使用coroutinesI完成的。我没有完成这是我个人的想法,但我认为可能使用一个线程来获取要“处理”的文件名列表,然后将它们传递到单独处理文件的线程池中。线程池处理完文件后,会将更新发布到ViewModel,回收器会使用DiffUtil更新该ViewModel。这意味着用户可以“看到”正在加载的文件,至少可以开始做一些事情。难道不可能只获取媒体文件列表,然后在RecyclerAdapter中提取onBindViewHolder()中的位图吗我也尝试过使用glide,但在开始时获取没有位图的音乐文件列表仍然需要很多时间!除使用协同程序外,还欢迎使用其他解决方案我们不限于协同程序“我想做的是,一旦我的应用程序启动,所有曲目都应立即在RecyclerView中填充适当的专辑艺术,不得延误”我最关心的是。。。为什么?我的意思是,你正在进行o(N)操作,让你的用户等待N。。。对于一个只需N秒就能打开的应用程序来说,这似乎是一个奇怪的设计/灌木油似乎很有趣,让我看看!是 啊使用coil可以让它发挥作用,但我还是个新手,面临着一些问题,比如在尝试获取图像时如何侦听任何错误,以及在加载图像后我希望它返回位图。我尝试了很多次搜索,但没有找到太多关于它的信息,可能是因为它没有被广泛使用?您可以通过ImageLoaderBuilder查询Mediastore只能使用.mp3,但我也尝试获取扩展名为.m4a和.wma的文件,这在Mediastore查询中不起作用!我尝试在recyclerview列表中使用coil,使过程更快,但是我也想在加载完成后返回位图,如果加载成功,则返回加载的位图,如果失败,则返回给定的错误位图我尝试过这样做,但将代码放入侦听器,并将位图分配给位图变量,但我始终得到一个空位图,所以这在我的case@Mr.Patel像其他评论一样,我也不知道你为什么希望这个过程立即进行。手动生成艺术品需要一些时间,只要您在后台显示通知,任何人都可以完全理解。其次,为什么不使用MediaStore播放mp3,而使用手动播放其他文件?这将有点复杂,但您可以创建自己的db,它从MediaStore复制现有uri,并为其他文件生成和保存albumart uri。除第一次运行外,后续运行应立即加载您想要的图片。playstore中的大多数应用程序都会立即显示所有音乐文件,不会有任何延迟。您可以查看google play music,其他所有应用程序都会立即显示,不会有任何延迟