0

So I have a class with static UI elements like so:

class MyClass {
    companion object {
        lateinit var item:ChannelItem
    }
}
// Item from groupie
class ChannelItem(var channel:Channel): Item<ViewHolder>() {
    // bind
    // getLayout
}

This seems to cause a memory leak, is there a quick way to fix it without changing the code too much?

I'm thinking about replacing the item with

var map = mutableMapOf<String, ChannelItem?>()

would this fix the memory leak? and if so why?

Thanks a lot

qwerty_99
  • 640
  • 5
  • 20

1 Answers1

2

Static UI elements make no sense in Android First off, UI objects are bound to a specific Activity. They can't be used from other activities or displayed outside of their Activity. So making them static doesn't bring value

Secondly, this will always be a memory leak. Each view has a reference to its Activity. Putting an Activity in a static variable means it can't be garbage collected, because there's a valid reference to it. That will basically cause every variable in that Activity to leak. Including the UI elements, which tend to be memory hungry (each image takes 4 bytes per pixel).

You need to rethink what you're trying to do with this code. I actually can't tell. If you made them static so you can change them from other activities- don't do that. Make them based off a model object, and alter the data in the model instead. Let the UI reinitialize itself based off the model.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • does this apply to fragments stored as static variables too (to share them across activities)? also will an assignment like `mystaticvar = null` enable the garbage collector to collect it? – qwerty_99 Nov 21 '21 at 22:15
  • Fragments also should not be shared as statics, because they can only be displayed in the Activity they were created with as context. And yes, that would leak their context if stored in a static. Nuling out all static references does clear it, but if you're keeping track of everything needed to do that, it would have been easier just not to make it a static at all. – Gabe Sechan Nov 21 '21 at 22:26
  • 1
    Basically, the only thing you should be sharing across activities is your app's data. Not its UI elements, and not its contexts. Those should belong exclusively to the Activity that created it and to the context itself. You can store them in local variables, or pass it to functions as a parameter. But it should not be saved in statics or any object that's lifecycle isn't a subset of the Activity. – Gabe Sechan Nov 21 '21 at 22:29
  • so if I have a fragment that I want to share across activities, i should not make it static? – qwerty_99 Nov 22 '21 at 16:35
  • 1
    No. You also shouldn't share it across Activities. Each Activity needs to make its own version. UI elements are bound to a single Activity, and won't work properly in others. The lifecycle will get all types of broken. – Gabe Sechan Nov 22 '21 at 16:52
  • okay, thanks a lot! – qwerty_99 Nov 22 '21 at 19:29
  • I need to create a floating view upon all activities, this view shows important infomations for user, so it's independent from any activity. and I need to use this view in any activity(all activies share same view), in this case, I have to create a static variable to reference this view which add into WindowManager directly, and the type is application_overlay, the code is below, how do I avoid using a static variable to reference a view? 【 val layoutParams = WindowManager.LayoutParams(), layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY】 – Chinese Cat Apr 12 '23 at 12:25