토이프로젝트 1-7 dagger 써보기 -2-
토이프로젝트 1-6 dagger 써보기 -1-
먼저 dagger를 쓰겠다고, build gradle에 추가해야겠지? app 모듈에 추가하고, 이제는 app에서 database를 빌드 해야하니깐 Room runtime도 추가하자. def dagger_version = "2.28.3" implementation "com.google.dagger:dagger:$dagg
www.lonewhite.com
에 이어서...
1. 어떤식으로 객체를 만들지 정의하는 Mudule
2. 1의 Module을 이용해서 여기에 넣어줘 라고 쓰는 Component
3. 이 컴포넌트를 만들고, 사용하는 부분
여기서 이제 2, 3 번을 해볼께..
2. 1의 Module을 이용해서 여기에 넣어줘 라고 쓰는 Component
코드를 먼저 보면
package com.lonewhite.finhelper.di.component
import com.lonewhite.finhelper.di.module.DataModule
import com.lonewhite.finhelper.test.TestActivity
import dagger.Component
import javax.inject.Singleton
@Singleton
@Component(modules = [DataModule::class])
interface ApplicationComponent {
@Component.Builder
interface Builder {
fun dataModule(dataModule: DataModule)
fun build(): ApplicationComponent
}
fun inject(testActivity: TestActivity)
}
내용은 간단해
@Component라고 써서 내가 컴포넌트요 하는거고
여기에 사용하는 모듈을 써주고
여기에 넣어줘라는 inject를 쓴게 다야.
나는 testActivity에서 사용할 꺼니깐 여기에 넣어줘 라고 정의한거지
그럼 끝. 정말 간단하지?
3. 이 컴포넌트를 만들고, 사용하는 부분
이제 이걸 초기화 해볼까?
초기화 하는 부분은 Application 코드에 추가해주면 됨
먼저 application 클래스를 만들자 아래처럼
package com.lonewhite.finhelper
import android.app.Application
class FinApplication: Application() {
}
그리고 이게 어플리케이션 코드요 라고 Manifest에 추가해주고.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name="com.lonewhite.finhelper.FinApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.FinHelper"
tools:targetApi="31">
<activity
android:name=".test.TestActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
그리고 이제 초기화 해보자.
builder를 이용해서 앱 처음 시작할때 초기화 되게 해주면 됨
코드를 먼저 보면
package com.lonewhite.finhelper.di.component
import com.lonewhite.finhelper.di.module.DataModule
import com.lonewhite.finhelper.test.TestActivity
import dagger.Component
import javax.inject.Singleton
@Singleton
@Component(modules = [DataModule::class])
interface ApplicationComponent {
@Component.Builder
interface Builder {
fun dataModule(dataModule: DataModule): Builder
fun build(): ApplicationComponent
}
fun inject(testActivity: TestActivity)
}
저렇게 해서 만들고, 나중에 쓰는 곳에서 applicationCompenent를 가져다가 inject를 해주면 되는거지
근데 DaggerApplicationComponent가 뭔지 궁금하지?
우리가 ApplicationComponent를 interface로 만들었자나? 그걸 대거가 알아서 코드넣고 만드는게 DaggerApplicationComponent 이거야. 아마 빤간줄 나올텐데 빌드 돌리면 잘 될테니 걱정말고.
이제 사용하는걸 알아볼까?
코드를 보면
package com.lonewhite.finhelper.test
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import com.lonewhite.finhelper.FinApplication
import com.lonewhite.finhelper.R
import com.lonewhite.finhelper.data.model.InvItem
import com.lonewhite.finhelper.data.repository.Repository
import java.util.Date
import javax.inject.Inject
class TestActivity : AppCompatActivity() {
@Inject
lateinit var repository: Repository
override fun onCreate(savedInstanceState: Bundle?) {
(applicationContext as FinApplication).applicationComponent.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
val textView = findViewById<TextView>(R.id.textView)
val getButton = findViewById<Button>(R.id.button1)
getButton.setOnClickListener{
val items = repository.getAllData()
textView.text = items.size.toString()
}
val setButton = findViewById<Button>(R.id.button2)
setButton.setOnClickListener{
val invItem = InvItem("test1", null, 55, Date(235235L), null)
repository.insertData(invItem)
}
}
}
저기서 @Inject 보이지? 근데 우리가 뭐 생성해주는 부분이 없지? 어디서 생성하냐면은...
(applicationContext as FinApplication).applicationComponent.inject(this)
그냥 저렇게만 해 두면 알아서 repository 객체를 넣어주는거야.
빌드를 해보면 아래 같은 파일들이 알아서 생겨
bulid/generated/source/kapt 에 생기는 어노테이션 보고 만들어진 코드인거지
예를 들어 하나 열어보면
// Generated by Dagger (https://dagger.dev).
package com.lonewhite.finhelper.di.component;
import com.lonewhite.finhelper.data.db.AppDatabase;
import com.lonewhite.finhelper.data.db.dao.InvItemDao;
import com.lonewhite.finhelper.data.repository.Repository;
import com.lonewhite.finhelper.di.module.DataModule;
import com.lonewhite.finhelper.di.module.DataModule_ProvideAppDatabaseFactory;
import com.lonewhite.finhelper.di.module.DataModule_ProvideContextFactory;
import com.lonewhite.finhelper.di.module.DataModule_ProvideInvItemDaoFactory;
import com.lonewhite.finhelper.di.module.DataModule_ProvideRepositoryFactory;
import com.lonewhite.finhelper.test.TestActivity;
import com.lonewhite.finhelper.test.TestActivity_MembersInjector;
import dagger.internal.Preconditions;
@SuppressWarnings({
"unchecked",
"rawtypes"
})
public final class DaggerApplicationComponent implements ApplicationComponent {
private final DataModule dataModule;
private DaggerApplicationComponent(DataModule dataModuleParam) {
this.dataModule = dataModuleParam;
}
public static ApplicationComponent.Builder builder() {
return new Builder();
}
private AppDatabase getAppDatabase() {
return DataModule_ProvideAppDatabaseFactory.provideAppDatabase(dataModule, DataModule_ProvideContextFactory.provideContext(dataModule));
}
private InvItemDao getInvItemDao() {
return DataModule_ProvideInvItemDaoFactory.provideInvItemDao(dataModule, getAppDatabase());
}
private Repository getRepository() {
return DataModule_ProvideRepositoryFactory.provideRepository(dataModule, getInvItemDao());
}
@Override
public void inject(TestActivity testActivity) {
injectTestActivity(testActivity);
}
private TestActivity injectTestActivity(TestActivity instance) {
TestActivity_MembersInjector.injectRepository(instance, getRepository());
return instance;
}
private static final class Builder implements ApplicationComponent.Builder {
private DataModule dataModule;
@Override
public Builder dataModule(DataModule dataModule) {
this.dataModule = Preconditions.checkNotNull(dataModule);
return this;
}
@Override
public ApplicationComponent build() {
Preconditions.checkBuilderRequirement(dataModule, DataModule.class);
return new DaggerApplicationComponent(dataModule);
}
}
}
이렇게 되어 있는데, dagger가 만들어준 factory에서 어떻게 가져와서 어떻게 넣게다 가 다 작성되어서 나와.
원래 우리가 다 저렇게 직접 짜야 하는데, 그 수고를 덜어준거지
그럼 다음번에는... 본격 mvvm을 하기 전에....
간단하게 코드 짤 수 있게, view binding을 알아볼려고