Capture Images and show in RecyclerView : Too much work on the main thread

55 Views Asked by At

I am trying to capture images in my Android App using camera and show it in a list using RecyclerView

But because the images are quite heavy in size (6-7 MB each) and my list is can contains approx 8-9 images, I can see this in my logs:-

06-08 17:22:44.318 14283 14283 I Choreographer: Skipped 40 frames!  The application may be doing too much work on its main thread.

And it's not just about the logs. I can even see that when I am trying to capture the image with camera in the foreground, sometimes(frequency : 30%) my application is getting killed and automatically recreated. Because of this, I am losing my images that were earlier captured.

This is my code to capture the image written in my SampleFragment.kt:-

fun onBtnTakePicture() {
        val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        outputFileName = "${System.currentTimeMillis()}.jpg"
        val photo = File(context!!.filesDir, outputFileName)
        val outputFileUri = FileProvider.getUriForFile(context!!, AUTHORITY_APP_FILES,photo)
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri)
        cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE)
    }

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(resultCode == AppCompatActivity.RESULT_OK){
            if(requestCode == CAMERA_REQUEST_CODE){
                    //To add to db, we need to add this in view model
                    transactionViewModel.addImagePathInList(outputFileName)

                    //to show in the UI, we need to add it into this list
                    myCardsList.add(FeatureCarouselCardData(outputFileName))

                    featureCardsView.notifyAdapaterAboutDataSetChange()
            }
        }
    }

private lateinit var featureCardsView: FeatureCarouselView

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
..........
..........
featureCardsView = binding.featureCardsView
featureCardsView.showFeatureCarouselCards(myCardsList)
..........
..........
}

Adapter object is created in my class extending the RecyclerView : FeatureCarouselView.kt

fun showFeatureCarouselCards(featureCarouselCards: List<FeatureCarouselCardData>){
        this.featureCarouselCards = featureCarouselCards

        featureCarouselAdapter = FeatureCarouselAdapter(context, featureCarouselCards)
        adapter = featureCarouselAdapter

    }

This is the onBindViewHolder function in my FeatureCarouselAdapter.kt class

override fun onBindViewHolder(holder: FeatureCarouselViewHolder, position: Int) {
        val currentItem = featureCarouselCards[position]
        var bitmap = mContext.resources.getDrawable(R.drawable.ic_file_not_found).toBitmap()
        Log.d(LOG_TAG, "currentItem in onBindViewHolder : "+currentItem)
        try {
            Log.d(LOG_TAG, "try")
            val photo = File(mContext.filesDir, currentItem.fileName)
            val outputFileUri = FileProvider.getUriForFile(mContext, AUTHORITY_APP_FILES,photo)
            bitmap = MediaStore.Images.Media.getBitmap(mContext.contentResolver, outputFileUri)
        }catch (e: FileNotFoundException) {
            Log.d(LOG_TAG, "catch filenotfound")
            e.printStackTrace()
        } catch (e: IOException) {
            Log.d(LOG_TAG, "catch ioexception")
            e.printStackTrace()
        }
        holder.imageView.setImageBitmap(bitmap)
    }

While I know that there are some tools that can be used to load images alternatively and efficiently like Picasso or Glide. But these needs INTERNET permissions to be added in the Manifest file.

I want to keep my app offline only. So want to avoid this.

How can I achieve this?

Update

I even tried using loading images using Glide:-

Glide.with(mContext)
                .load(outputFileUri)
                .into(holder.imageView)

But still, I am facing the same problem. So, what could be the possible root cause for my issue?

0

There are 0 best solutions below