So I have a (Kotlin) data class that gets instantiated in my startup activity (we'll just call the object dataObj
). I have two other activities that need access to the dataObj
that was instantiated on startup. I know I could have my data class implement the Serializable
interface so that I could pass the object between the three activities using intents. But I also have been thinking that I could use a static variable in the constructor so that I could easily just grab the values for the class. I'm just trying to figure out what is recommended and what is good practice.

- 2,124
- 3
- 23
- 42
-
2What about a singleton? – tomerpacific Dec 22 '18 at 20:45
-
Never used a singleton but that looks like a good option. – Slaknation Dec 22 '18 at 21:02
-
@tomerpacific that only works right/correctly if you save it to `onSaveInstanceState` in `BaseActivity` and restore it only once when app starts but `savedInstanceState != null` – EpicPandaForce Dec 22 '18 at 21:52
4 Answers
One big issue with this is that static variables don't survive Android low-memory state, but sending intent between survives. Also read here about static variable. (Link)

- 1,260
- 1
- 8
- 10
-
Technically they don't survive, but you CAN save them to `onSaveInstanceState` bundle, it's just that all activities need to do it, and should only be restored *once* (if app is starting but the first `savedInstanceState` is `!= null`). – EpicPandaForce Dec 22 '18 at 21:53
You have two options here:
- Send it via
Intent
after implementingSerializable
orParcelable
by you data class, - Save your data object to
.txt
file and read it when you need it.
static
it is not created for this kind of things and You shouldn't use it in this case.
In my opinion You should go with first option.

- 1,245
- 12
- 19
-
What about a singleton? I am beginning to think that a Singleton might be a good option (thanks tomerpacific) – Slaknation Dec 22 '18 at 21:01
-
that only works right/correctly if you save it to `onSaveInstanceState` in `BaseActivity` and restore it only once when app starts but `savedInstanceState != null` – EpicPandaForce Dec 22 '18 at 21:53
-
You can use it also but the question is, is it not a overkill for Your needs? https://en.wikipedia.org/wiki/Overengineering – DawidJ Dec 22 '18 at 21:57
It really depends on your use case, but I'd generally recommend against static implementations (to include singletons, see What is so bad about singletons?). They become hard to test adequately over time and can (in short) lead to many other problems depending on implementation.
If it is a relatively simple object where state change is rare, only done in one Activity at a time, and/or irrelevant, implementing a Parcelable
and passing that to each Activity
via an Intent
is probably best.
If this is a complex object or an object that can change dynamically, the preferable solution would be to use a dependency injection platform (such as Koin if you're using Kotlin) to instantiate the data and provide it as a dependency. Koin is pretty straight forward, a very basic implementation from the Koin website (and missing just a few lines to be complete):
// Injected by constructor
class MyViewModel(val repo : MyRepository) : ViewModel()
// declared ViewModel using the viewModel keyword
val myModule : Module = module {
viewModel { MyViewModel(get()) }
single { MyRepository() }
}
// Just get it
class MyActivity() : AppCompatActivity() {
// lazy inject MyViewModel
val vm : MyViewModel by viewModel()
}
In this case, your object would be something like MyRepository()
in the example. You'd just have to add the startKoin([list of modules])
from there. If you wanted MyRepository()
in your Activity
you'd include it like val myRepo: MyRepository by inject()
. I don't know if this is outside the scope of your project though, it all depends on what you're trying to do exactly.

- 914
- 7
- 15
This isn't the best method (although there really isn't a perfect way to do this), but you could instantiate it in a custom Application class.
class App : Application() {
val yourObject by lazy { YourObject() } //by lazy is useful if the Object needs to hold a Context or something that isn't immediately available
}
Add android:name=".App"
to the application
tag in your manifest so your App class is actually used. .App
assumes it's in the root of your application package.
Then, from anywhere you have a reference to a Context, you can do something like:
(context.applicationContext as App).yourObject
to access the Object.

- 16,775
- 6
- 49
- 63