Skip to main content

Koject v1.1.0 - Enhanced Android support

· 4 min read
Mori Atsushi

I have released Koject v1.1.0, which includes enhanced support for Android application development. In this article, I will introduce the new features and the Component feature that enables the features.

日本語で読む →

Inject ViewModels

In Android application development, it is common to add dependencies such as Repository to AndroidX's ViewModel and use it from Activity or Fragment. With Koject v1.1.0, you can automatically inject ViewModel dependencies.

First, add the @Provides annotation to the class used in ViewModel and register it with the DI container. By adding @Singleton, it can register as a singleton.

@Singleton
@Provides
class UserRepository {
/* ... */
}

@Singleton
@Provides
class ContentRepository {
/* ... */
}

Next, define the ViewModel. You can inject the classes registered with the DI container in the constructor. Add @Provides annotation and @ViewModelComponent annotation to ViewModel.

@Provides
@ViewModelComponent
class TopViewModel(
private val userRepository: UserRepository,
private val contentRepository: ContentRepository,
): ViewModel() {
/* ... */
}

Finally, use the ComponentActivity.injectViewModels() function to obtain the ViewModel.

class TopActivity : ComponentActivity() {
private val viewModel: TopViewModel by injectViewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/* ... */
}
}

For Fragment, please use the Fragment.injectViewModels() function instead.

class TopFragment : Fragment() {
private val viewModel: TopViewModel by injectViewModels()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
/* ... */
}
}

Additional dependencies are required to use this feature. For more details, please refer to the documentation.

Updated (2023/03/14)

injectViewModels has been renamed to lazyViewModels in v1.2.0.

// Until v1.1.0
private val viewModel: TopViewModel by injectViewModels()

// Since v1.2.0
private val viewModel: TopViewModel by lazyViewModels()

Inject into Composable

Koject 1.1.0 also added support for Jetpack Compose and Compose Multiplatform.

You can use the rememberInject() Composable function to use the provided class in a Composable function.

@Composable
fun Sample(
controller: SampleController = rememberInject()
) {
/* ... */
}

rememberInject() can be called inside Composable functions, but it is recommended to use it as a default argument. This will make it easier to replace during testing.

Please do not to use the inject() function inside Composable functions. Creating an instance for each rendering or performing inject processing multiple times may cause performance degradation.

@Composable
fun Sample(
controller: SampleController = inject() // DO NOT!!
) {
/* ... */
}

For the setup method, please refer to the documentation.

Component feature

In ViewModel, you can inject a SavedStateHandle to save the state:

@Provides
@ViewModelComponent
class SavedStateViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
/* ... */
}

Koject has added the Component feature to provide instances created by the platform, such as SavedStateHandle.

A Component is a grouping of types registered with the DI container. By default, the all types are registered in the root component. By annotating with a Component annotation, they can be registered in another component.

// Registered in RootComponent
@Provides
class NormalClass

// Registered in SomeComponent
@SomeComponent
@Provides
class ComponentClass

Types registered in a component can only reference types within the same component and types in the root component.

You can also provide additional dependencies to a component.

Koject defines @ViewModelComponent by default and adds SavedStateHandle to @ViewModelComponent. Therefore, be aware that you cannot inject SavedStateHandle into a component other than @ViewModelComponent.

You can learn how to create a custom component in the documentation.

Experimental

The Component feature is an experimental API. It may change in the future.

Koject is evolving

I believe that Koject v1.1.0 will provide even stronger support for Android application development. In order to make the library even easier to use, I plan to add even more features in the future.

If you notice anything, please feel free to provide feedback on the Issue page.