Creating Activity with Constructor Arguments

Kenny Hadisaputra
3 min readMay 16, 2020

As an Android Developer myself, I find it pretty annoying that I can’t create an Activity with arguments in the constructor.

Why? Because I pretty much hate it that when I want to inject some dependencies into the Activity, I have to add @Inject annotation to it (supposedly we use dagger). And to do it, I have to make it public lateinit var which means you can actually re-assign new value to it and you can do it from outside that Activity.

Well, people might say that as long as it works, that’s not really bad. And I’m pretty sure that you will almost never re-assign value to that variable. But won’t it be good enough if we can actually prevent that from happening at all?

And one more thing, if you use dagger, you have to basically call injection method to the activity class itself via .inject(this) as it is required for field injection. Can we eliminate that injection method totally?

Well, I have a good news and bad news for you.

The good news is …

AppComponentFactory to the rescue

We now have the capability to do so, yay.

AppComponentFactory is a factory class that you can extend from and inside, you can return your custom Activity, Application, Service, BroadcastReceiver, and ContentProvider.

How does it work? Well, if you ever have tried ViewModelFactory or FragmentFactory, all of them practically works in the same way.

When you want to create an Activity, you provide the class in Intent(context, MyActivity::class.java) . That activity class will be passed to AppComponentFactory, and from there you can read the activity class and then return the implementation of your activity.

Let’s see a snippet for it.

MainActivity.kt class with params constructor

Here, we want to create a MainActivity with a simple string as its constructor argument. Normally, we cannot do this and the compiler will complain that it needs a no-argument constructor for the activity.

But by using AppComponentFactory, we can create it.

Custom AppComponentFactory

MyAppComponentFactory extends from AppComponentFactory and we can override some of its methods. But since we just want to create an Activity here, I only override the instantiateActivity method.

In the instantiateActivity method, we have parameter ClassLoader, String for class name, and the Intent itself. To get the class of the activity, we can straight up use the ClassLoader.loadClass(String) method and pass the class name as the argument. Then, after we know what class it is, we can return the implementation of the Activity for that class.

If you want to pass the extras of the Intent, for example an id of something, and pass it as argument constructor to the destination activity, you can get it via the intent parameter.

After you finish ramping up that class, you need to adjust yourAndroidManifest file.

Define the AppComponentFactory in the Manifest file

Here, you just need to change some attributes in the application tag by putting your custom AppComponentFactory class as value to the android:appComponentFactory key and also don’t forget to put tools:replace="android:appComponentFactory"there to override the default AppComponentFactory.

Just like that, you can now have your Activity with constructor arguments. Cool, isn’t it?

Wow, that’s pretty good

But…, I did tell you that I have a bad news for you.

It only supports Android P (API 28) and above

Usually, there will be backport version of official Android library for older API level. But, this time there won’t be one. Why? Because all of the components which creation you can override in the AppComponentFactory are part of the underlying Android framework and the older API doesn’t know how to deal with this new way of instantiating these components (which is one of the reasons why Google recommend Single Activity).

So, this definitely don’t have much uses for now as older API will just crashed, unless you make an app only for yourself.

To check the full sample, here is the link on my github.

Feel free to give any feedback and I will be back with more things to share. Thanks.

--

--

Kenny Hadisaputra

Android Developer and Kotlin Enthusiast (can also do a little bit iOS)