0

I am developing an application in which I can choose a background for a recyclerview (an imageview behind a recyclerview). After selecting the image from the gallery, I would like to send it to the firebase. However when uploading the image my app is freezing and I can't scroll the recyclerview

My code:

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK) {
        /* code */
             else if (requestCode == BG_GALLERY_REQUEST_CODE) {
                val selectedPicture = data?.data
                val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
                val cursor = applicationContext.contentResolver.query(selectedPicture!!, filePathColumn, null, null, null)
                cursor!!.moveToFirst()

                val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                val picturePath = cursor.getString(columnIndex)
                val bitmap = BitmapFactory.decodeFile(picturePath)
                cursor.close()
                backgroundUtils.salvarBackground(bitmap)

                val byteArrayOutputStream = ByteArrayOutputStream()
                bitmap?.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream)
                val dadosImagem = byteArrayOutputStream.toByteArray()

                val storageReference = ConfiguracaoFirebase.getFirebaseStorage()
                val imagemRef = storageReference
                        .child("imagens")
                        .child("backgrounds")
                        .child(UsuarioFirebase.getId() +
                                FileUtils.IMAGE_EXTENSION)
                val uploadTask = imagemRef.putBytes(dadosImagem)
                uploadTask.addOnSuccessListener {
                    imagemRef.downloadUrl.addOnSuccessListener { uri ->
                        ConfiguracaoFirebase.backgroundRef()
                                .child(UsuarioFirebase.getId())
                                .setValue(uri)
                        Log.e("upload", uri.toString())
                    }
                }.addOnFailureListener { exception ->
                    Log.e("upload", exception.message)
                }
            }
        } else if (resultCode == Activity.RESULT_CANCELED) {
            Log.i("REQUEST", "canceled")
        } else {
            toast(getString(R.string.oops_ocorreu_algum_erro))
        }
    }

I also tried to execute the upload code inside an AsyncTask but the problem persisted. How to solve this error?

Thanks in advance

MMG
  • 3,226
  • 5
  • 16
  • 43
Vitor Ferreira
  • 1,075
  • 1
  • 14
  • 28

2 Answers2

1

Set images in new thread like this:

Thread timer = new Thread()
            {
                public void run()
                {
                    try
                    {
                        sleep(2000);
                       runOnUiThread(new Runnable() {
                        public void run() {
                             splash.setImageResource(R.drawable.billboard_image);
                        }
                    });

                        sleep(2000);
                        runOnUiThread(new Runnable() {
                            public void run() {
                                 splash.setImageResource(R.drawable.square);
                            }
                        });
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    finally
                    {
                       System.out.println("finally");
                    }
                }
            };
            timer.start();
zinonX
  • 330
  • 2
  • 20
  • Probably shouldn't do this messy callback logic in kotlin. In kotlin coroutines are a better fit. And using Thread.sleep is very discouraged in production, it just blocks the thread (very resource intensive). And again you're sending the runnable to run on UI thread so this solution may have 0 effect, or may even negative effect cuz you're making new threads for no reason. – Animesh Sahu May 05 '20 at 14:05
  • Actually in your code ui thread or main thread is overloading so i just suggest you new thread – zinonX May 05 '20 at 14:14
  • Actually its not me who asked the question, and btw the ui and main threads are the same in the android, see: https://stackoverflow.com/questions/3261370/is-main-thread-the-same-as-ui-thread – Animesh Sahu May 05 '20 at 14:17
0

Possibly because all the lifecycle methods run on main thread of android. And you're using long running and resource intensive tasks like BitmapFactory.decodeFile(), Bitmap.compress(), etc in the callback (function onActivityResult) itself.

You should use other threads for doing that, but wait a thread is itself an intensive resource and creating a new thread everytime you want to send an image is not favourable.

You could use coroutines in here, using the ViewModel.

// Dispatchers.Default is used for resource intensive tasks and is backed by a CommonPool of threads, that can be reused with another coroutine
// NonCancellable overrides the job on ViewModelScope to become non-cancellable
viewModelOwner.viewModelScope.launch(Dispatchers.Default + NonCancellable) {
    // Your intensive task right here
    // if you want to do some operation like updating ui just use runOnUiThread{/* code */}
}
Animesh Sahu
  • 7,445
  • 2
  • 21
  • 49