Why does AdView cause memory leak? code is in thre...
# compose
m
Why does AdView cause memory leak? code is in thread
Copy code
AndroidView(
    factory = { context ->
        LinearLayout(context).apply {
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )

            addView(
                AdView(context).apply {

                    layoutParams = LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.WRAP_CONTENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT
                    ).apply { gravity = Gravity.CENTER_HORIZONTAL }

                    adSize = AdSize.FULL_BANNER

                    adUnitId = Constants.getBannerAdId()

                    loadAd(AdRequest.Builder().build())
                }
            )
        }
    }
)
w
I think the context passed in AndroidView is the immediate context- what if you call
Copy code
AdView(context.applicationContext).apply
? Does that solve it?
g
How do you know that there is a leak?
m
I'll try
g
It’s incorrect to use applicationContext for views
m
@gildor whenever I comment the AdViewComposable the leak will fix, I use leak canary library
g
Please share your leak canary log
m
┬─── │ GC Root: Local variable in native code │ ├─ java.lang.Thread instance │ Leaking: UNKNOWN │ Retaining 100.5 kB in 2423 objects │ Thread name: 'AdWorker(NG) #1' │ ↓ Thread.target │ ~~~~~~ ├─ java.util.concurrent.ThreadPoolExecutor$Worker instance │ Leaking: UNKNOWN │ Retaining 48 B in 1 objects │ ↓ ThreadPoolExecutor$Worker.this$0 │ ~~~~~~ ├─ java.util.concurrent.ScheduledThreadPoolExecutor instance │ Leaking: UNKNOWN │ Retaining 276 B in 9 objects │ ↓ ThreadPoolExecutor.workQueue │ ~~~~~~~~~ ├─ java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue instance │ Leaking: UNKNOWN │ Retaining 100.0 kB in 2409 objects │ ↓ ScheduledThreadPoolExecutor$DelayedWorkQueue.queue │ ~~~~~ ├─ java.util.concurrent.RunnableScheduledFuture[] array │ Leaking: UNKNOWN │ Retaining 100.0 kB in 2408 objects │ ↓ RunnableScheduledFuture[].[0] │ ~ ├─ java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask instance │ Leaking: UNKNOWN │ Retaining 99.9 kB in 2407 objects │ ↓ FutureTask.callable │ ~~~~~~~~ ├─ java.util.concurrent.Executors$RunnableAdapter instance │ Leaking: UNKNOWN │ Retaining 99.9 kB in 2406 objects │ ↓ Executors$RunnableAdapter.task │ ~~ ├─ bat instance │ Leaking: UNKNOWN │ Retaining 99.9 kB in 2405 objects │ ↓ bat.a │ ~ ├─ bav instance │ Leaking: UNKNOWN │ Retaining 99.8 kB in 2404 objects │ ↓ azb.listeners │ ~~~~~~~~~ ├─ ays instance │ Leaking: UNKNOWN │ Retaining 99.3 kB in 2387 objects │ ↓ ays.b │ ~ ├─ ayl instance │ Leaking: UNKNOWN │ Retaining 99.3 kB in 2385 objects │ ↓ azb.listeners │ ~~~~~~~~~ ├─ ays instance │ Leaking: UNKNOWN │ Retaining 99.3 kB in 2384 objects │ ↓ ays.b │ ~ ├─ ayu instance │ Leaking: UNKNOWN │ Retaining 99.2 kB in 2380 objects │ ↓ ayu.a │ ~ ├─ ayl instance │ Leaking: UNKNOWN │ Retaining 99.2 kB in 2379 objects │ ↓ azb.listeners │ ~~~~~~~~~ ├─ ays instance │ Leaking: UNKNOWN │ Retaining 99.2 kB in 2378 objects │ ↓ ays.b │ ~ ├─ ayu instance │ Leaking: UNKNOWN │ Retaining 14.4 kB in 545 objects │ ↓ ayu.a │ ~ ├─ azd instance │ Leaking: UNKNOWN │ Retaining 14.3 kB in 544 objects │ ↓ azb.listeners │ ~~~~~~~~~ ├─ ays instance │ Leaking: UNKNOWN │ Retaining 14.3 kB in 543 objects │ ↓ ays.b │ ~ ├─ com.google.android.gms.ads.nonagon.util.concurrent.x instance │ Leaking: UNKNOWN │ Retaining 16 B in 1 objects │ ↓ x.a │ ~ ├─ com.google.android.gms.ads.nonagon.util.concurrent.z instance │ Leaking: UNKNOWN │ Retaining 48 B in 2 objects │ ↓ z.d │ ~ ├─ azd instance │ Leaking: UNKNOWN │ Retaining 2.2 kB in 29 objects │ ↓ azf.b │ ~ ├─ com.google.android.gms.ads.nonagon.render.cm instance │ Leaking: UNKNOWN │ Retaining 44 B in 1 objects │ ↓ cm.c │ ~ ├─ com.google.android.gms.ads.nonagon.util.net.a instance │ Leaking: UNKNOWN │ Retaining 40 B in 1 objects │ b instance of github.masterj3y.ads.rewarded.RewardedAdActivity with │ mDestroyed = true │ ↓ a.b │ ~ ╰→ github.masterj3y.ads.rewarded.RewardedAdActivity instance ​ Leaking: YES (ObjectWatcher was watching this because github.masterj3y. ​ ads.rewarded.RewardedAdActivity received Activity#onDestroy() callback ​ and Activity#mDestroyed is true) ​ Retaining 83.3 kB in 1773 objects ​ key = a4f7e739-6c21-4cd8-bfe4-4d3de76f4c1c ​ watchDurationMillis = 12293 ​ retainedDurationMillis = 7287 ​ mApplication instance of co.newgates.speechtype.AppBase ​ mBase instance of androidx.appcompat.view.ContextThemeWrapper METADATA Build.VERSION.SDK_INT: 29 Build.MANUFACTURER: Xiaomi LeakCanary version: 2.7 App process name: co.newgates.speechtype Stats: LruCache[maxSize=3000,hits=2656,misses=68414,hitRate=3%] RandomAccess[bytes=3652045,reads=68414,travel=34333282365,range=26694430,size=32 401942] Heap dump reason: 3 retained objects, app is not visible Analysis duration: 13364 ms
For your information I use the Composable inside a LazyColumn
g
Indeed, it looks like a known issue of AdView https://github.com/square/leakcanary/issues/403
Some use different hacks https://www.py4u.net/discuss/624683
m
Sounds I should ApplicationContex to AdView Is that ok? You said it's incorrect
g
It’s definitely incorrect for usual views, you will lost Activity context wrapper (including theme)