1

I want to generate a list of QR codes (10 in this example).

I'm using RecyclerView adapter and ZXing library, where generateQrCode method I took from here: https://stackoverflow.com/a/25283174/9311961, which returns a bitmap on 256 x 256 (512 would take too much time):

My first approach was to generate the QRs on the background thread, like this:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val context = holder.itemView.context
    val qrCode = qrCodeList!![position]

    println("TIME AT $position: ${getCurrentDateTime()}")
    holder.imageIv.setImageBitmap(generateQrCode(context, qrCode.qr))

    // ...
}

I got these times as response:

I/System.out: TIME AT 0: 2019-08-23 11:25:14
I/System.out: TIME AT 1: 2019-08-23 11:25:15
I/System.out: TIME AT 2: 2019-08-23 11:25:16
I/System.out: TIME AT 3: 2019-08-23 11:25:16
I/System.out: TIME AT 4: 2019-08-23 11:25:17
I/System.out: TIME AT 5: 2019-08-23 11:25:17
I/System.out: TIME AT 6: 2019-08-23 11:25:18
I/System.out: TIME AT 7: 2019-08-23 11:25:18
I/System.out: TIME AT 8: 2019-08-23 11:25:19
I/System.out: TIME AT 9: 2019-08-23 11:25:20

=> 6 seconds

But the problem is, that this approach will block my screen until the QRs are generated.

My second approach was to generate the QRs using RxJava, avoiding background thread:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val context = holder.itemView.context
    val qrCode = qrCodeList!![position]

    val array = arrayListOf(qrCode.qr, holder.imageIv, position)
    println("TIME START: ${getCurrentDateTime()}")

    Single.just(array)
        .subscribeOn(Schedulers.computation()).map {
            val bitmap = generateQrCode(context, it[0] as String)
            arrayListOf(bitmap, it[1], it[2])
        }
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(this::onGenerateQrCodeSuccess, this::onGenerateQrCodeError)

    // ...
}

private fun onGenerateQrCodeSuccess(array: ArrayList<Any>) {
    val qrCode = array[0] as Bitmap
    val imageView = array[1] as AppCompatImageView
    val position = array[2] as Int

    println("TIME AT $position: ${getCurrentDateTime()}")
    imageView.setImageBitmap(qrCode)
}

private fun onGenerateQrCodeError(throwable: Throwable) {
    println("ERROR WHILE GENERATING QR: $throwable")
}

I got these times as response:

I/System.out: TIME START: 2019-08-23 12:15:32
I/System.out: TIME AT 0: 2019-08-23 12:15:43
I/System.out: TIME AT 2: 2019-08-23 12:15:44
I/System.out: TIME AT 3: 2019-08-23 12:15:44
I/System.out: TIME AT 1: 2019-08-23 12:15:45
I/System.out: TIME AT 4: 2019-08-23 12:15:54
I/System.out: TIME AT 6: 2019-08-23 12:15:55
I/System.out: TIME AT 7: 2019-08-23 12:15:55
I/System.out: TIME AT 5: 2019-08-23 12:15:55
I/System.out: TIME AT 8: 2019-08-23 12:15:57
I/System.out: TIME AT 9: 2019-08-23 12:15:57

=> 25 seconds

It's much more time than generating QRs from background thread.

It would be nice to achieve the time I got in first approach without having my screen blocked.

So how could I obtain a fast QRs generating by using RxJava (or in any other way), to not have my screen blocked until these are displayed?

Robert Pal
  • 714
  • 1
  • 7
  • 15

1 Answers1

0

Most probably the problem is in computation scheduler. Internally it uses fixed amount of threads (equals to amount of cores on a device). So just replace Schedulers.computation() with Schedulers.io() and everything should work faster.

eleven
  • 6,779
  • 2
  • 32
  • 52