Dependencies Injection in Android – Part 2: How to manage when the application appears multiple logic threads?

Tram Ho

Introduction

In part 1 , I have gone through an example to understand what Dependencies Injection is like in Android. We have also manually created an AppContainer class that is ready for steps and ready to create an instance, to serve for creating another instance. And we can use that container anywhere in the entire app. In this part 2, let’s take a look at how when the application starts to grow, there are many threads to be processed. This article will go through 2 parts: more centralized viewmodel management and container management when applying more processing threads.

Manage ViewModel more centralized

In fact, our UserViewModel is hardly initialized directly, but thanks to ViewModelProvider. That’s thanks to how ViewModelProvider works:

  • If ViewModelProvider creates us a certain viewmodel, it will return ViewModel if it exists, if not, it will create new ViewModel instance.
  • The ViewModel created by ViewModelProvider will be attached to the associated scope (activity or fragment). You can see more here .

This is very useful when fragment for some reason gets killed and recreated (e.g. screen rotation or memory is freed when not enough), if the viewmodel is initialized directly from the ViewModel. (), each time a fragment creates a new one, it will also create a new viewmodel and process it from scratch. Another advantage is in the problem that multiple fragments share data from the same Activity viewmodel they attach when they have a thread. Fragments are not affected by each other and do not care about each other. And viewmodel is only clear when Activity ends.

Normally, the syntax for creating viewmodel through ViewModelProvider is as follows: ViewModelProvider(context).get(LoginViewModel::class.java)

Another thing to note is that when our LoginViewModel needs to pass parameters in the constructor, for example, we must pass the UserRepository, but ViewModelProvider can only create ViewModel without parameters. Now you will need ViewModelProvider.Factory to initialize the viewmodel with parameters in the constructor

So now we can use the LoginViewModelFactory in the AppContainer to initialize the LoginViewModel. We will try using it in LoginActivity offline:

Ok so we managed to manage viewmodel more centrally thanks to ViewModelProvider.Factory, right?

As the application logic expands

We’re just dealing with the login flow for the app, right. Please consider the application when there are other functions such as Register, or Setting. Each function thread will have a container to create viewmodels that process data and logic for those streams. Then our AppContainer will now include all those containers. AppContainer will grow larger and contain more and more instances for individual threads.

With different threads, we may want objects to live only within the scope of that thread. For example, when creating a LoginUserData (containing the username and password for the login stream only), we don’t want to store data from the old login thread, we should have a new instance for each new one. This results in optimizing the application chart and the flow container can also be more strenuous. We will need to remember to delete the instance containing the data when the thread ends.

Take a clearer example as follows: Now in the login stream, we have 2 fragments (2 screens in order, can be seen in the login stream of many apps like Gmail or Skype) LoginUsernameFragment just enter username and LoginPasswordFragment to enter password, be attached to LoginActivity. These two Fragments want:

  • Access to the same LoginUserData instance needs to be shared until the login process is finished.
  • Create a LoginUserData instance when the login thread re-starts. Then we need LoginContainer to handle this login flow as follows:

And at LoginActivity we will initialize ViewModel, initialize LoginUserData. Fragments such as LoginUsernameFragment and LoginPasswordFragment will share these instances of data and logic. However, at the end of the login thread, ViewModel can be cleared (), but LoginUserData, we have to manually delete it. Please delete in onDestroy () as follows:

As you can see, we have to manually manage the scope and lifecycle of the containers, optimize and remove containers that are no longer needed to free up memory. We need to do this carefully and properly to avoid leading to minor bugs and memory leaks in the app.

Conclude

Manual Dependencies Injection is a good technique for creating scalable Android apps. We use containers as a way to provision and share instances or data in different flows of your application in a more centralized place like thanks to factories. However, it is clear that as our application gets older there will be a lot of boilerplate code, scopes and lifecycle that needs to be handled with care and this can be prone to errors. We also have yet to handle instances that need Singleton property across the application.

In the next part, I will introduce Dagger, how to use Dagger to automate this process instead of how to manually manage DIs like the last two parts.

Thank you for reading.

Reference: https://developer.android.com/training/dependency-injection/manual

Share the news now

Source : Viblo