下载带有翻新和rxJava的文件列表

时间:2019-06-11 15:12:23

标签: android kotlin retrofit

我正在尝试从具有翻新和rxjava的api下载文件列表,我读了很多书,但是我无法弄清楚翻新和rxjava如何协同工作,而且我不确定观察者必须使用哪种线程

我正在尝试更改应用程序的文件下载过程,该过程最初是使用doAsync(Anko)进行的,该应用程序在具有api 19和互联网连接速度缓慢的非常有限的平板电脑中运行。最初的问题是,平板电脑在第一个文件下载中会出现内存泄漏(大约200个文件,使用100 mb的内存(全部))。因此,经过长时间的研究,我决定尝试使用Rx和翻新程序重写下载过程的代码(但我在Kotlin或Movil方面没有太多经验)。

我的模特

data class File(
         val id: String
)      //staging

data class Movimientos(val borrar: List<File>,
                       val descargar: List<File>,
                       val estructura: List<Nodo>)

data class Nodo( val id: String,
                 val root: String,
                 val name: String,
                 val file: Boolean,
                 val descargado: Boolean,
                 val version: Int)

我的服务

//return a json with a list of files to download (and to more list -not important for now-)
 @GET("index.php")
    fun getMovimientos(@Query("r") r: String = "movimientos",
                       @Query("imei") id: String,
                       @Query("access-token") accesstoken: String): Observable<Movimientos>


    @Streaming
    @GET("index.php")
    fun getArchivo(@Query("r") r: String = "descarga",
                    @Query("id") fileID: String,
                    @Query("access-token") accesstoken: String): Observable<ResponseBody>


    companion object {
        fun create(): WikiApiService {

            val retrofit = Retrofit.Builder()
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("https://url/api.biblioteca/")
                    .build()

            return retrofit.create(WikiApiService::class.java)
        }
    }

要求获取要下载的列表并调用下载过程


private fun beginSearch(searchString: String) {
        disposable = wikiApiServe.getMovimientos("movimientos", "d55a374eebc242a5", "XXXXXXXXXXXX")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())

                .subscribe(
                        {
                            result -> txt_search_result.text = "${result.estructura.size} tamaño estructura"
                            Log.d("Estructura: ", "Es: ${result.estructura}")
                            //var aux =10

                            result.estructura.forEach {
                                nodo ->
                                if (nodo.file/) {
                                    //aux--
                                    descargarArchivo(nodo.id)

                                }
                            }
                        },
                        { error -> Toast.makeText(this, error.message, Toast.LENGTH_SHORT).show() }
                )




    }

要求下载功能

private fun descargarArchivo(id: String){
        disposable = wikiApiServe.getArchivo("descarga", id, "XXXXXXXXXXX")
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(
                        {
                            //result -> txt_search_result.text = "${result.estructura.size} tamaño estructura"
                            totalDescargas = totalDescargas +1
                            Log.d("Descargado: ", "Id archivo: $id bytes: ${it.bytes().size} Total descargas: $totalDescargas")

                            //total.text = totalDescargas
                        },
                        { error -> Toast.makeText(this, error.message, Toast.LENGTH_SHORT).show() }
                )

    }

当我运行代码时,该应用程序会下载一些文件(大约五个),然后不再执行其他操作(logcat向我发送了很多GC_FOR_ALLOC警告和跳帧信息)。我尝试限制对下载方法的调用(以编程方式将计数变量(限制为10),以避免尝试尝试下载200个文件),但仍然可以发送GC_FOR_ALLOC,并且我必须添加一些代码来下载其他190个文件每十个批次(但是我认为这不是最好的方法)。即时消息,我不得不使用观察者列表,并使用flatMap调用downlad函数,这是另一个麻烦。但是我不知道如何使用这种方法。

我尝试使用另一个线程(每次下载一个新线程),但是线程池有错误

1 个答案:

答案 0 :(得分:1)

我将转换代码以使用Observable.fromIterable和flatMap,flatMap的重载带有maxConcurrency参数,可用来避免创建Schedulers.io()默认将执行的线程数量不受限制。 / p>

在包含foreach循环的订阅之前,添加对flatMap的调用,如下所示。然后,每次调用getArchivo的结果都会调用您的订阅,因此将其内容替换为您当前在getArchivo订阅中拥有的代码

private fun beginSearch(searchString: String) {
    disposable = wikiApiServe.getMovimientos("movimientos", "d55a374eebc242a5", "XXXXXXXXXXXX")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap { result ->
            Observable.fromIterable(result.estructura)
                .flatMap({ nodo ->
                    wikiApiServe.getArchivo("descarga", nodo.id, "XXXXXXXXXXX")
                    .subscribeOn(Schedulers.io())
            }, 4)
        }
        .subscribe(
            {
            totalDescargas = totalDescargas +1
            Log.d("Descargado: ", "Id archivo: $id bytes: ${it.bytes().size} Total descargas: $totalDescargas")
            },
            { error -> Toast.makeText(this, error.message, Toast.LENGTH_SHORT).show() }