본 글은 Android에서 Dagger2를 사용하여 Firebase DatabaseReference를 DI 하는 것을 설명하므로
Dagger2, Firebase, DI에 대한 설명은 생략합니다.
관련하여 구글링을 했지만 개념을 이해하기 쉽지 않았습니다.
큰 개념은 이해가 가지만 실 구현은 더더욱 와닿지가 않더군요.
우선 간단한 수준으로 DI를 성공시킨 뒤 까먹지 않기 위해 기록을 남깁니다.
- @Module + @Provides
- @Inject
- @Component
1. @Module + @Provides
- Class에 선언되는 어노테이션으로 DI에 사용될 실제 구현체들을 모듈 단위로 모아놓은 어노테이션으로 이해된다.
- Module 어노테이션이 선언된 클래스에는 @Provides 어노테이션을 메서드 앞에 붙여주어 DI에 사용될 구현체를 정의할 수 있다.
2. @Inject
@Module + @Provides의 구현체를 주입받을 타겟이 된다.
Class, Method, Field에 사용 가능하지만 본 글에서는 Field에 사용한 예를 보인다.
3. @Component
@Module + @Provides와 @Inject를 연결해주는 Bridge라고 보면 된다.
예제의 구성 요소
- UsersActivity.java (Android Activity - @Inject)
- UserDataSource.java (Interface)
- UserRepository (Class - UserDataSource의 구현체)
- RepositoryComponent (@Component)
- RepositoryModule (@Module + @Provides)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public interface UserDataSource { interface LoadUsersCallback { void onUsersLoaded(List<User> users); void onDataNotAvailable(); } interface GetUserCallback { void onUserLoaded(User user); void onDataNotAvailable(); } void getUser(@NonNull String userId, @NonNull GetUserCallback callback); void saveUser(@NonNull User user); } |
2. 다음은 이를 구현한 구현체 UserRepository 클래스입니다.
우선 getUser는 구현하지 않았고, saveUser만 구현된 상태입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class UserRepository implements UserDataSource { private DatabaseReference ref; public UserRepository(DatabaseReference databaseReference) { this.ref = databaseReference; } @Override public void getUser(@NonNull String userId, @NonNull GetUserCallback callback) { } @Override public void saveUser(@NonNull final User user) { ref.child("users").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { ref.child("users").child(user.getId()).setValue(user); } @Override public void onCancelled(DatabaseError databaseError) { } }); } } | cs |
Firebase의 실시간 데이터베이스 사용법은 아래 링크를 통해 확인 바랍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @Module public class RepositoryModule { private DatabaseReference databaseReference; public RepositoryModule(Context context) { int playServicesStatus = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context); if (playServicesStatus == ConnectionResult.SUCCESS) { databaseReference = FirebaseDatabase.getInstance().getReference(); } } @Singleton @Provides UserDataSource provideUserDataSource() { return new UserRepository(databaseReference); } @Singleton @Provides GroupDataSource provideGroupDataSource() { return new GroupRepository(databaseReference); } } | cs |
4. RepositoryComponent: @Component 를 정의한 인터페이스입니다.
@Component는 반드시 Interface에 붙여져야 합니다.
1 2 3 4 5 6 | @Singleton @Component(modules = {RepositoryModule.class}) public interface RepositoryComponent { void inject(UsersActivity target); } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class UsersActivity extends AppCompatActivity { RepositoryComponent repositoryComponent; @Inject UserDataSource userDataSource; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bank_accounts); repositoryComponent = DaggerRepositoryComponent.builder() .repositoryModule(new RepositoryModule(getApplicationContext())).build(); repositoryComponent.inject(this); } } | cs |
댓글
댓글 쓰기