Android – DI – Container

Container

Prepare main container and sub containers. This container contains all dependencies.

This idea is from Google Android Manual dependency injection page

Sample

Prepare AppContainer to use components for entire app.

This class contains

  • data sources
  • Repository with data sources
  • Singleton object
  • Model factory
  • Sub container (to manage lifecycle)

AppContainer.kt

This is main container which has all injections

class AppContainer {

    val retrofit = Retrofit.Builder()
        .baseUrl("https://dj110.it")
        .build()
        .create(DataRetrofitService::class.java)

    val remoteDataSource = DataRemoteDataSource(retrofit)
    val localDataSource = DataLocalDataSource()
    val dataRepository = DataRepository(localDataSource, remoteDataSource)


    // Create model from factory
    val dataViewModelFactory = DataViewModelFactory(dataRepository)

    // Consider lifecycle (only create and use when to use)
    var dataContainer : DataContainer? = null
}

DataContainer

Data Container is sub component (container) to use other Activity, Fragment. Recommend to create one container for Activity.

class DataContainer(val dataRepository: DataRepository) {
    val dataData = Data("")

    val dataModelFactory = DataViewModelFactory(dataRepository)
}

ModelFactory.kt

This is ViewModel (not Android Architect Component one), factory interface

interface ModelFactory<T> {
    fun create() : T
}

Implement this interface to support returning ViewModel

DataViewModelFactory.kt

This is ViewModel Factory class.

class DataViewModelFactory(private val dataRepository: DataRepository) : ModelFactory<DataViewModel> {

    override fun create(): DataViewModel {
        return DataViewModel(dataRepository)
    }
}

DataViewModel.kt

This is ViewModel class. To manipulate UI data etc…

The key of MVVM

class DataViewModel (private val dataRepository: DataRepository) {
}

DataRepository.kt

Repository is data manipulation class (retrieve data mainly)

class DataRepository (
    private val localDataSource: DataLocalDataSource,
    private val remoteDataSource: DataRemoteDataSource
) {
}


class DataLocalDataSource() {}

class DataRemoteDataSource(private val dataService: DataRetrofitService) {}

DataRetrofitService.kt

For retrofit. More details, please check other my blog (Android kotlin Retrofit).

interface DataRetrofitService {

    @GET("/data")
    fun getData() : Call<Data>
}

Data.kt

It’s just model data class

data class Data(val name: String)

MyApplication.kt

This is override application class. This class creates container to manage this as everything.

class MyApplication : Application() {

    val appContainer = AppContainer()
}

Of course, we need to register this in AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.daiji110.disample1">

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Let’s use ViewModel from 2 Activity

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var dataViewModel : DataViewModel

    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // App Container
        val appContainer = (application as MyApplication).appContainer
        dataViewModel = DataViewModel(appContainer.dataRepository)
    }
}

DataActivity.kt

class DataActivity : AppCompatActivity() {

    // View Model
    private lateinit var dataViewModel: DataViewModel

    // Data
    private lateinit var dataData: Data

    // Container (Application level)
    private lateinit var appContainer: AppContainer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // LocalContainer in AppContainer
        // LocalContainer has :  ViewModel factory and Data(model)

        appContainer = (application as MyApplication).appContainer
        // Create this activity level container
        dataViewModel = appContainer.dataContainer?.dataModelFactory!!.create()
        dataData = appContainer.dataContainer?.dataData!!
    }

    override fun onDestroy() {
        appContainer.dataContainer = null
        super.onDestroy()
    }
}

See. DataContainer is destroyed when calling onDestroy().

Android 未分類
スポンサーリンク
Professional Programmer2

コメント