Home > Back-end >  How to notify adapter if the fragment deatched or destroyed [needed for Admob NativeAd AdViewHolder]
How to notify adapter if the fragment deatched or destroyed [needed for Admob NativeAd AdViewHolder]

Time:07-04

In my app, I have implemented ad mob native ads inside my PostAdapter class, I have 7 different fragments, and I need to know when the fragment is detached or destroyed to call nativeAd.destroy() to avoid leaks like said in the documentation

Be sure to use the destroy() method on loaded native ads. This frees up utilized resources and prevents memory leaks.

so my trying to solve this problem, I created an Interface and put it into adapter contractor and a method that returns a boolean state when the fragment isDetached or isRemoving but both didn't work


interface AdapterAndFragmentsUtils {

    fun isFragmentDestroyed(): Boolean

}

The PostAdapter class

class PostAdapter(
    items: List<Item>, private val adapterAndFragmentsUtils: AdapterAndFragmentsUtils
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val items: List<Item>


.....some unrelated issue codes


 inner class AdViewHolder(private val binding: NativeAdRowBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bindAdData() {
            val adLoader =
                AdLoader.Builder(binding.root.context, "ca-app-pub-3940256099942544/2247696110")
                    .forNativeAd { nativeAd: NativeAd ->

//                        populateNativeADView(nativeAd)

                        val styles =
                            NativeTemplateStyle.Builder().withMainBackgroundColor(
                                ColorDrawable(
                                    ContextCompat.getColor(
                                        binding.root.context,
                                        R.color.backgroundColor
                                    )
                                )
                            )
                                .build()
                        val template: TemplateView = binding.myTemplate
                        template.setStyles(styles)
                        template.setNativeAd(nativeAd)


                        if (adapterAndFragmentsUtils.isFragmentDestroyed()) {
                            nativeAd.destroy()
                            Log.d(TAG,"nativeAdDestroyed")
                            return@forNativeAd
                        }

//
                    }
                    .withAdListener(object : AdListener() {

                        override fun onAdClicked() {
                            super.onAdClicked()
                            Log.d(TAG, "onAdClicked: ")
                        }

                        override fun onAdClosed() {
                            super.onAdClosed()
                            Log.d(TAG, "onAdClosed: ")
                        }

                        override fun onAdLoaded() {
                            super.onAdLoaded()
                            Log.d(TAG, "onAdLoaded: ")
                        }

                        override fun onAdOpened() {
                            super.onAdOpened()
                            Log.d(TAG, "onAdOpened: ")
                        }

                        override fun onAdFailedToLoad(adError: LoadAdError) {
                            // Handle the failure by logging, altering the UI, and so on.
                            Toast.makeText(
                                binding.root.context,
                                adError.message,
                                Toast.LENGTH_SHORT
                            ).show()

                            Log.e(TAG, "onAdFailedToLoad: ${adError.cause.toString()}")
                        }
                    })
                    .withNativeAdOptions(
                        NativeAdOptions.Builder()
                            // Methods in the NativeAdOptions.Builder class can be
                            // used here to specify individual options settings.

                            .build()
                    )
                    .build()

            adLoader.loadAd(AdRequest.Builder().build())
        }

        }
    }


Implementation of the interface in each fragment

class HomeFragment : Fragment(), AdapterAndFragmentsUtils {

....

override fun isFragmentDestroyed(): Boolean {
        Log.d(TAG, "isFragmentDestroyed: ${this.isDetached}")
        return isDetached
    }

CodePudding user response:

Instead of an interface method, you can create a method in the adapter itself

first, make nativeAd is global

private var nativeAd: NativeAd?=null

then create the method

fun destroyNativeAd(){
        nativeAd?.destroy()
      
    }

and finally, you can call it from fragments onDestroyView

 override fun onDestroyView() {
        super.onDestroyView()
        adapter.destroyNativeAd()
    }
  • Related