All Projects → beworker → Magnet

beworker / Magnet

Licence: apache-2.0
Dependency injection for modular Android applications

Programming Languages

java
68154 projects - #9 most used programming language
kotlin
9241 projects

Projects that are alternatives of or similar to Magnet

Dagger2
Kotlin Dagger2 example project
Stars: ✭ 145 (-16.18%)
Mutual labels:  dependency-injection
Container
A lightweight yet powerful IoC container for Go projects
Stars: ✭ 160 (-7.51%)
Mutual labels:  dependency-injection
Mandarinets
Mandarine.TS is a typescript, decorator-driven framework that allows you to create server-side applications. Mandarine.TS provides a range of built-in solutions such as Dependency Injection, Components, ORM and more. Under its umbrella, Mandarine.TS has 4 modules: Core, Data, Security and MVC, these modules will offer you the requirements to build a Mandarine-powered application.
Stars: ✭ 161 (-6.94%)
Mutual labels:  dependency-injection
Hiboot
hiboot is a high performance web and cli application framework with dependency injection support
Stars: ✭ 150 (-13.29%)
Mutual labels:  dependency-injection
Iquephoto
Android Image Editor Application.
Stars: ✭ 156 (-9.83%)
Mutual labels:  dependency-injection
Android Clean Architecture
Showcasing a Clean Architecture approach from our Android applications framework!
Stars: ✭ 160 (-7.51%)
Mutual labels:  dependency-injection
Fluentvalidation.blazor
Fluent Validation-powered Blazor component for validating standard <EditForm> 🌌 ✅
Stars: ✭ 140 (-19.08%)
Mutual labels:  dependency-injection
Tsyringe
Lightweight dependency injection container for JavaScript/TypeScript
Stars: ✭ 2,761 (+1495.95%)
Mutual labels:  dependency-injection
Fx
A dependency injection based application framework for Go.
Stars: ✭ 2,383 (+1277.46%)
Mutual labels:  dependency-injection
Kapsule
Minimalist dependency injection library for Kotlin.
Stars: ✭ 162 (-6.36%)
Mutual labels:  dependency-injection
Dig
A reflection based dependency injection toolkit for Go.
Stars: ✭ 2,255 (+1203.47%)
Mutual labels:  dependency-injection
Dingo
🐺 Easy, fast and type-safe dependency injection for Go.
Stars: ✭ 154 (-10.98%)
Mutual labels:  dependency-injection
Upcomingmovies
Movies app written in Swift 5 using the TMDb API and demonstrating Clean Architecture, Dependency Injection, MVVM and Coordinators.
Stars: ✭ 160 (-7.51%)
Mutual labels:  dependency-injection
Dry Auto inject
Container-agnostic constructor injection mixin
Stars: ✭ 149 (-13.87%)
Mutual labels:  dependency-injection
Qframework
Unity3D System Design Architecture
Stars: ✭ 2,326 (+1244.51%)
Mutual labels:  dependency-injection
Sactive Web
🚀 A dependency injection web framework for Node.js.
Stars: ✭ 143 (-17.34%)
Mutual labels:  dependency-injection
Awilix
Extremely powerful Inversion of Control (IoC) container for Node.JS
Stars: ✭ 2,269 (+1211.56%)
Mutual labels:  dependency-injection
Ioc
🦄 lightweight (<1kb) inversion of control javascript library for dependency injection written in typescript
Stars: ✭ 171 (-1.16%)
Mutual labels:  dependency-injection
Swinjectautoregistration
Swinject extension to automatically register your services
Stars: ✭ 164 (-5.2%)
Mutual labels:  dependency-injection
Flama
🔥 Fire up your API with this flamethrower
Stars: ✭ 161 (-6.94%)
Mutual labels:  dependency-injection

Build Status Kotlin version badge Maven Central License

🧲 Magnet

Magnet is a concise, scope tree based Dependency Injection (DI) library designed for highly modular Android applications. It consists of two parts: an annotation processor (Kotlin) and a reflection free runtime library (Java + Kotlin).

Design

Magnet defines and opetates on two core concepts: Scopes and Instances.

Scope is a container for instances. Scopes can be combined into a hierarchical tree by referencing parent scopes. The most top scope of the tree hierarchy, which has no parent scope, is called the root scope.

Instance is a concrete occurance of an injected type. Instances can be allocated in scopes (scoped instances) or outside of scopes (unscoped instances).

The Dependency Rule

Scopes depend on each other using the strong dependency rule - scope dependency can only point torwards its parent scope. The dependency direction between two scopes enforces the direction of dependencies between instances allocated in those scopes. Instances allocated in a parent scope can know nothing about instances allocated in its child scopes. This simple design rule helps preventing memory leaks and allows safe disposal of child scopes and garbage collecting instances allocated there.

Getting Started

In the example below we will compose a very naive MediaPlayer which loads media using a MediaLoader and then plays the media.

fun main() {
   val rootScope = MagnetScope.createRootScope()
   val playerScope = rootScope.createSubscope {
      bind(Uri.parse("https://my-media-file"))
   }
   
   // mark 1
   val mediaPlayer = playerScope.getSingle<MediaPlayer>()
   mediaPlayer.playWhenReady()
   
   // mark 2
   Thread.sleep(5000)
   playerScope.dispose()
   
   // mark 3
}

// MediaPlayer.kt
interface MediaPlayer {
   fun playWhenReady()
}

@Instance(type = MediaPlayer::class, disposer = "dispose")
internal class DefaultMediaPlayer(
   private val assetId: Uri,
   private val mediaLoader: MediaLoader
) : MediaPlayer {
   override fun playWhenReady() { ... }
   fun dispose() { ... }
}

// MediaLoader.kt
interface MediaLoader {
   fun load(mediaUri: Uri): Single<Media>
}

@Instance(type = MediaLoader::class)
internal class DefaultMediaLoader() : MediaLoader {
   override fun load(mediaUri: Uri): Single<Media> { ... }
}

The diagram below shows how Magnet manages the scope hierarchy when different marks of the main function are reached.

At Mark 1, two scopes are created and the Uri instance gets bound into the playerScope.

At Mark 2, mediaPlayer and mediaLoader instances get allocated in respective scopes. mediaPlayer is allocated in the playerScope because one of its dependencies, the Uri, is located in playerScope. Magnet cannot move mediaPlayer up to the rootScope because this would break the dependency rule described above. mediaLoader has no dependencies, that's why it is allocated in the rootScope. This instance allocation logic is specific to Magnet DI and is called auto-scoping. See developer documentation for more detail.

At Mark 3, the playerScope gets disposed and all its instances are garbage collected.

For more information refer to Magnet documentation.

Documentation

  1. Developer Guide
  2. Dependency auto-scoping
  3. Scope Inspection
  4. How to Inject Android ViewModels
  5. Blog: Magnet - an alternative to Dagger
  6. Co2Monitor sample app
  7. Another sample app

Features

  • Minimalistic API
  • Auto-scoping of instances
  • Hierarchical, disposable scopes
  • Kotlin friendly annotation
  • Injection into Kotlin constructors with default arguments
  • Injection from binary libraries
  • Dependency inversion
  • No direct references to Magnet generated code
  • No reflection for injection, apt generated factory classes
  • Extensible - some magnetx extensions are available
  • Customizable - custom factories and instance selectors

Why Magnet?

Magnet was crafted with simplicity and development speed in mind. It lets developers spend less time on DI configuration and do more other stuff, also more mistakes when used inattentively. Magnet motivates you writing highly modular apps because it makes DI so simple. It can even inject instances from the libraries added in build scripts without necessity to adapt source code. Magnet could be interesting for those, who needs an easy to configure and simple DI with more runtime control.

Why not Magnet?

If compile time consistency validation is your highest priority, I recommend using awesome Dagger2 instead. You will spend slightly more time on DI configuration but Dagger2 lets you keep it highly consistent and error prone (in most cases) very early in the development cycle - at compile time.

Peace ✌️ and have fun.

Gradle

Kotlin

repositories {
   mavenCentral()
}
dependencies {
   api 'de.halfbit:magnet-kotlin:<version>'
   kapt 'de.halfbit:magnet-processor:<version>'
}

Java

repositories {
   mavenCentral()
}
dependencies {
   api 'de.halfbit:magnet:<version>'
   annotationProcessor 'de.halfbit:magnet-processor:<version>'
}

Proguard & R8

-keep class magnet.internal.MagnetIndexer { *; }

License

Copyright 2018-2020 Sergej Shafarenka, www.halfbit.de

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].