Android developer dependency injection

Android Dependency Injection With Koin

March 29, 2021

Dependency injection is a programming technique that makes a class independent of its dependencies. This is made possible by decoupling the usage of an object from its creation. Many Android developers are familiar with Java-based dependency injection frameworks such as Dagger and Guice.

However, some frameworks are written completely in Kotlin for Kotlin. These frameworks include Koin and Kodein. This article goes through how to manage dependencies in Android using the new dependency injection framework — Koin.

Prerequisites

To follow through with this tutorial, you will need to:

  1. Have Android Studio installed.
  2. Have a basic knowledge of building Android applications.
  3. Have a basic understanding of Kotlin programming language.

Let’s get started!

What exactly is dependency injection

Being a software developer, you must, or might have heard about dependency injection but didn’t really understand what it is. You might even be asking yourself, why should I use this technique?

How important is it? Have I ever used it? Well, the answer to the last question is pretty simple. You have but without any dependency injections framework.

Consider the following scenario. You have two classes, A and B. Class B requires an instance of A for it to perform a specific task. It is correct to say that class B directly depends on class A.

Therefore, we often find ourselves creating an instance of the dependent class before using it or pass it as a parameter. All these are forms of dependency injection. This is fine for a small project.

However, as the project scales, maintenance and testing become challenging. This is where dependency injection frameworks come into play.

A dependency injection framework helps us to create and manage dependencies. As mentioned earlier, there are many Java-based Android dependency injection frameworks. However, with the increased adoption of Kotlin on Android, the demand for libraries written completely in Kotlin for Kotlin is rising.

Koin is a dependency injection framework that conforms to this need. It is a lightweight framework, easy to learn, and does not have much boilerplate code. Let’s see how we can use this framework to manage dependencies in our Android applications.

Getting started with Koin

Koin is fairly simple. All we need to do is create our classes, tell Koin how to create the dependencies, then we can call them whenever/wherever we need them.

Before we move any further, create an empty activity project and give it a name of your choice. Wait for the project build to complete then add the following dependency on your app-level build.gradle file.

Let’s go ahead and create some classes.

Creating project components

We are going to need some components that depend on each other for demonstration. Let’s create a scenario. Create a Kotlin file and in it add the following code.

The first class is a Student class, a student has a course of study and a friend to play with. Therefore, the Student class depends on those classes.

It needs them to call or access the study() and play() functions contained in the Course and Friend classes respectively. To solve this dependency we add the two classes as parameters.

This means that the Student class can not be instantiated without instances of Course and Friend classes.

Open the MainActivity file and replace the onCreate function with the following code.

The application uses View binding to access the default TextView with an id of text_view . Visit this link to learn more about View binding.

The code creates instances of all the classes.

Upon running the application, the text view will display:

There is nothing wrong with the application as it is. But, as we mentioned earlier, depending on this kind of dependency injection will make the application hard to maintain as it scales. Let’s see how Koin can help us manage these dependencies.

Creating a Koin module

Koin uses modules to create dependencies. Create a new Kotlin file with the name ‘module’ and add the following code.

Читайте также:  Star wars для android кэш

The module function as the name suggests is used to create a module. single is used to create a singleton instance. This means that Koin will return the same instance of the class when the dependency is needed.

We have made Course a singleton since we assume that all the students do the same course. factory , on the other hand, is used when we want a new instance of the class every time we call it.

We have used the factory for both Friend and Student classes since we want a new instance whenever we call them. The get function is used to get the required dependency only if it has been specified in the module.

It detects the type of dependency we need and fetches it for us. That’s all we need for the module. Let’s go ahead and start Koin.

Starting Koin

Starting Koin is fairly simple. Create an application class with the name of your choice and add the following code to start Koin.

We use the startKoin function to start Koin.

And that’s it! Koin is fully set up. Now, let’s use Koin in our MainActivity .

Replace the onCreate method of the MainActivity with this.

The reduction of lines of code is noticeable. by inject delegate is used to lazily inject dependencies. We can also use the get function to get the dependency non-lazily .

Run the application again.

The code works fine, but, this time we have employed a dependency injection framework that helps a lot in ensuring our project is maintainable and can be easily tested.

Conclusion

In this article, we have gone through dependency injection and how to manage dependencies using a Kotlin dependency injection known as Koin. We have seen how Koin is easy to set up and work with.

We have also seen how dependency injection helps us in making our applications maintainable. I hope this tutorial gives you the basics you need to start using this great and lightweight framework.

Peer Review Contributions by: Wanja Mike

About the author

Peter Kayere is an undergraduate student at Jomo Kenyatta University of Agriculture and Technology studying Computer Technology. Peter has a great passion in software development particularly mobile web and android application development. Peter’s most used programming languages are Kotlin and Javascript.

Want to learn more about the EngEd Program?

Discover Section’s community-generated pool of resources from the next generation of engineers.

Источник

Koin – это Dependency Injection или Service Locator?

В Android-разработке для DI традиционно используют Dagger 2, очень мощный фреймворк с кодогенерацией. Но есть проблема: новичкам сложно его использовать. Сами принципы DI просты и понятны, но Dagger усложняет их. Можно жаловаться на поголовное падение грамотности программистов, но от этого проблема не исчезнет.

С появлением Kotlin появилась возможность писать удобные вещи, которые были бы практически невозможны с использованием Java. Одной из таких вещей стал Koin, который является не DI, а Service Locator, который многими трактуется как anti-pattern, из-за чего многие принципиально его не используют. А зря, ведь у него очень лаконичный API, упрощающий написание и поддержку кода.

В данной статье я хочу помочь новичкам разобраться с разграничением понятий Dependency Injection и Service Locator, но не с самим Koin.

Dependency Injection

Прежде всего, что такое Dependency Injection? Простыми словами, это когда объект принимает зависимости извне, а не создаёт или добывает их сам. Приведу пример. Предположим, у нас есть интерфейс Engine , его реализация, а также класс Car , который зависит от Engine . Без использования DI это может выглядеть вот так

Если переписать класс Car с использованием подхода DI, то может получиться вот это:

Всё просто – класс Car не знает, откуда приходит реализация Engine , при этом заменить эту самую реализацию легко, достаточно передать её в конструктор.

Service Locator

Попробуем разобраться с Service Locator. Тут тоже ничего сложного – это некий реестр, который по запросу может предоставить нужный объект. Пока я предлагаю отойти в сторону от Koin и представить некий абстрактный ServiceLocator, без деталей реализации, но с простым и понятным API.

У нас есть возможность добавить в наш реестр некую зависимость, а также получить эту зависимость. Вот пример использования с нашими двигателями и машинами:

Это отдалённо похоже на DI, ведь класс Car получает зависимость извне, не зная о реализации, но у данного подхода есть проблема – мы ничего не знаем о зависимостях класса Car , есть ли они вообще. Можно попробовать такой подход:

Теперь мы знаем, что у Car есть зависимости, но всё ещё не знаем какие. Т.е. это не решение нашей проблемы. Но есть ещё один вариант:

Читайте также:  Изменить размер кнопок android

Это и есть Dependency Injection в чистом виде. С Koin это бы выглядело вот так:

Увы, нам всё ещё необходимо обращаться к Koin для получения зависимостей, но это никоим образом не противоречит принципам Dependency Injection.

UPDATE. По просьбе kranid приведу максимально простой пример на Dagger 2.

Источник

Dependency Injection guidance on Android — ADS 2019

According to our introduction to Dependency Injection (DI), we believe you should always use DI principles in your applications. If you’re developing a professional Android app, use Dagger to better manage your dependencies.

We recommended using Dagger for medium and large apps; for small apps or pet projects, it doesn’t matter the tool you use, but the sooner you add Dagger to your project, the better it will be and the less you will have to refactor in the future.

If you compare the cost of managing your dependencies when using Dagger vs any other tool visually, Dagger starts with a relatively high cost but plateaus as the app gets bigger.

Dagger really shines with:

  • Performance. Without reflection and the code being generated at build time, Dagger can provide the best in class performance.
  • Correctness. Dagger gives you security at build time. If a type is not available in the DI application graph, you won’t be able to build the project instead of getting those crashes at runtime.
  • Scalability. Dagger is built to scale and be suitable for large applications such as Gmail, Google Photos or YouTube.

DI and Dagger are complex topics, for this reason we’re providing documentation and samples to learn these professional tools.

New Documentation

We just released a set of documentation to help you with this. We’d like to help both beginners and more experienced users by giving good practices.

New documentation available:

  • DI Overview: What’s DI and the benefits of using it in your project.
  • Manual DI: To better understand the benefits of DI and what Dagger can do for you, you should try DI yourself. In this page, we show how you can do DI manually in your app.
  • Dagger basics: Benefits of adding Dagger to your project and what it does under the hood.
  • Using Dagger in an Android app: Learn all the concepts of Dagger from scratch by adding Dagger to a typical Android app.
  • Dagger in a multi-module application: How to use Dagger in a modularised app with both regular Gradle modules and dynamic feature modules.

New Codelab

Apart from the documentation, the best way you can learn a topic is with hands on code. We released a new codelab called: Using Dagger in an Android app. It starts with a manual DI implementation that you’ll be migrating to Dagger flow by flow of the app.

By the end of it, you’ll build an application graph like this!

Complete the codelab to understand the main concepts of Dagger so you can apply them to your project accordingly.

Easier Dagger in Android

We want to make Dagger more accessible to small applications by reducing the amount of code you have to write. We’re working on a new initiative that will make Dagger simpler in Android. What will be changing?

  • The work you do for Dagger Components can be automated! We’ll have some predefined Components that can simplify the work for you.
  • It will be integrated with the rest of Jetpack and will provide an easy integration with ViewModels, WorkManager and Navigation.
  • Kotlin-friendly. We want Dagger to work seamlessly when written in Kotlin and expand its capabilities to make it work with delegates and other Kotlin powerful features.
  • Dagger Modules are the way to provide information to the Dagger graph. It’s important they stay and serve the same functionality in the new initiative.

Stay tuned, we’re working on that.

dagger.android

dagger.android is a library on top of Dagger that reduces boilerplate code when using Dagger in Android framework classes (e.g. Activities or Fragments).

Even though it helped with boilerplate, we think we can do better. Since the new Android approach is radically different, no major improvements are planned for this library but we’re committed to maintaining it until a suitable stable replacement is available.

If you’re using dagger.android, keep using it. If you’re starting a new project, consider dagger.android as an alternative and use if it fits your use case. We’ll provide migration guides from both Dagger and dagger.android code to the new initiative.

Conclusion

Use Dependency Injection and use Dagger! We’re already working on making it better. For more information, check the Android Dev Summit 2019 recording about this topic:

Читайте также:  Драйвер е1550 для андроид

Источник

Dependency injection on Android with Hilt

Dependency injection (DI) is a technique widely used in programming and well suited to Android development, where dependencies are provided to a class instead of creating them itself. By following DI principles, you lay the groundwork for good app architecture, greater code reusability, and ease of testing. Have you ever tried manual dependency injection in your app? Even with many of the existing dependency injection libraries today, it requires a lot of boilerplate code as your project becomes larger, since you have to construct every class and its dependencies by hand, and create containers to reuse and manage dependencies.

By following DI principles, you lay the groundwork for good app architecture, greater code reusability, and ease of testing.

The new Hilt library defines a standard way to do DI in your application by providing containers for every Android class in your project and managing their lifecycles automatically for you.

Hilt is built on top of the popular DI library Dagger so benefits from the compile time correctness, runtime performance, scalability, and Android Studio support that Dagger provides. Due to this, Dagger’s seen great adoption on 30% of top 10k apps of the Google Play Store. However, because of the compile time code generation, expect a build time increase.

Since many Android framework classes are instantiated by the OS itself, there’s an associated boilerplate when using Dagger in Android apps. Unlike Dagger, Hilt is integrated with Jetpack libraries and Android framework classes and removes most of that boilerplate to let you focus on just the important parts of defining and injecting bindings without worrying about managing all of the Dagger setup and wiring. It automatically generates and provides:

  • Components for integrating Android framework classes with Dagger that you would otherwise need to create by hand.
  • Scope annotations for the components that Hilt generates automatically.
  • Predefined bindings and qualifiers.

Best of all, as Dagger and Hilt can coexist together, apps can be migrated on an as-needed basis.

Hilt in action

Just to show you how easy to use Hilt is, let’s perform some quick DI in a typical Android app. Let’s make Hilt inject an AnalyticsAdapter into our MainActivity .

First, enable Hilt in your app by annotating your application class with the @HiltAndroidApp to trigger Hilt’s code generation:

Second, tell Hilt how to provide instances of AnalyticsAdapter by annotating its constructor with @Inject :

And third, to inject an instance of AnalyticsAdapter into MainActivity , enable Hilt in the activity with the @AndroidEntryPoint annotation and perform field injection using the @Inject annotation:

For more information, you can easily check out what the new annotations do in the cheat sheet section below.

Comes with Jetpack support!

You can use your favourite Jetpack libraries with Hilt out of the box. We provide direct injection support for ViewModel, WorkManager, Navigation, and Compose so far.

For example, to inject a Architecture Components ViewModel LoginViewModel into a LoginActivity : annotate LoginViewModel with @HiltViewModel , annotate the constructor with @Inject , and use it in an @AndroidEntryPoint activity or fragment as you’d expect:

Learn more about Jetpack support in the docs.

Start using Hilt

If you’re intrigued by Hilt and want to learn more about it, here’s some resources for you to learn in the way you prefer:

Getting started with Hilt

Learn how to add Hilt in your Android app with this guide.

Documentation

If you’re new to DI or Dagger, check out our guide to add Hilt to an Android app. Alternatively, if you already know Dagger, we’re also providing documentation on dagger.dev.

If you’re just curious about the new annotations and what you can do with Hilt, check out this cheat sheet in the section below.

For Dagger users

If you’re already using Dagger or dagger.android in your app, check out this migration guide or the codelab mentioned below to help you switch to Hilt. As Dagger and Hilt can coexist together, you can migrate your app incrementally.

Codelabs

To learn Hilt in a step-by-step approach, we just released two codelabs:

Sample code

Do you want to see how Hilt is used in existing apps? Go check its usage in the Google I/O 2020 app and in the dev-hilt branch of the Android architecture-samples Github repository.

Cheat sheet

This cheat sheet allows you to quickly see what the different Hilt and Dagger annotations do and how to use them.

Источник

Оцените статью