얼마전 제 블로그의 포스트에서 Dagger2를 이용하는 방법을 간단하게 적어보았습니다.

Android 개발에서 Dagger2이용해보기.

그런데 여기서 @Scope에 대한 설명이 없었던 것 같습니다.

@Scope ... 실질적으로는 Dagger2에서는 @Singleton annotation을 많이 사용합니다. Singleton은 굳이 자세히 설명을 안해도 다들 잘 알고 계시리라 봅니다. 객체 주입에서 @Singleton annotation을 적용해 두면.. 전체 App의 Scope안에서 Singleton객체가 생성되어 주입 됩니다. 그렇다면 다른 custom scope는 없을까요? 물론 @Scope annotation의 custom을 만들어서 사용합니다. 예를 들어서 Activity life cycle에서만 존재할 수 있는 객체 주입을 위해선 @PerActivity라던지 아니면 fragment life cycle에서만 객체 주입이 유지될 수 잇는 @PerFragment같은 custome scope annotation을 만들어 사용할 수 있습니다.



http://fernandocejas.com/wp-content/uploads/2015/04/composed_dagger_graph1.png


그럼 @Scope 를 이용한 예를 들어 볼 까 합니다.

이전에 예를 들었던 포스트인

Fragment에서 onActivityResult 결과 받기.

의 내용을 Dagger2를 이용한 방법으로 변경할려고 합니다. 주된 내용은 기존의 내용에서 EventBus객체를 Singleton pattern으로 생성해서 사용했습니다. 그럼 Dagger2를 이용해서 해당 샘플을 변경하면 어떻게 될까요?

우선 EventBus.java 입니다.

public class EventBus extends Bus {
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
handler.post(new Runnable() {
@Override
public void run() {
EventBus.super.post(event);
}
});
}
}
}

보시는 것과 같이 일반 객체와 별 다를 게 없습니다.


그럼 EventBusModule.java 입니다.

@Module
public class EventBusModule {
@Singleton
@Provides
EventBus provideEventBus() {
return new EventBus();
}
}

해당 모듈에서 EventBus를 제공해줄 때 @Singleton annotation이 붙었습니다. 이건 해당 객체를 Singleton으로 제공해 준다는 겁니다.


그리고 EventBusModule의 객체를 Inject를 하기 위한 Bridge역활을 해주는 ApplicationComponent.java 입니다.

@Singleton
@Component(
modules = {
ApplicationModule.class,
EventBusModule.class
}
)
public interface ApplicationComponent {
EventBus getEventBus();
}

해당 Component도 @Singletone으로 적용해두었습니다.


해당 Component자체도 Singleton scope에서 사용하겠다는 내용 입니다.


만약 Activity life cycle에서만 사용할 수 있는 scope를 만든다면

@Scope
@Retention(RUNTIME)
public @interface PerActivity {
}

로 만든다면 원하는 scope에다가 @PerActivity annotation을 적용하면 됩니다.


예제는..

https://github.com/drcarter/RetriveActivityResult 에서 retrive_activity_result_dagger 브랜치를 보시면 됩니다.

https://github.com/drcarter/RetriveActivityResult/tree/retrive_activity_result_dagger



singleton패턴이라고 하면 단 하나의 객체만을 생성해 주는 패턴입니다.
싱글톤 패턴을 만들려면 클래스 안에 자신의 클래스 포인터가 있어야 하고, 전역으로 그 클래스의 변수도 필요하겠죠.
하지만 template방법으로 하게 되면, 단순히 기존의 클래스를 상속하는 것만으로 만들 수 있는 방법을 알게 되었습니다.

#pragma once
#include 
#include 

template < typename T >
class Singleton
{
protected:
	Singleton()
	{
		assert(!m_kInstance);
		long long offset = (long long)(T *)1 - (long long)(Singleton *)(T *)1;
		m_kInstance = (T *)((long long)this + offset);
	}
	~Singleton()
	{
		assert(m_kInstance);
		m_kInstance = 0;
	}

public:
    static T * instance()
    {
        if (m_kInstance == NULL)
			m_kInstance = new T;
        return m_kInstance;
    };
    static void destroyInstance()
    {
		if(m_kInstance) {
			delete m_kInstance;
			m_kInstance = NULL;
		}
    };

private:
    static T * m_kInstance;
};

template  T* Singleton::m_kInstance = 0;

이런식으로 기본의 singleton template 클래스를 만들어 두고 이 클래스를 단순히 상속하여 사용하면 됩니다.
사용 방법은

class MyClass : public Singleton
{
private:
public:
    void MyMethod();
}
이런식으로 상속하여 자신의 원하는 클래스를 싱글톤으로 만들고 이 상속받은 클래스를 사용하는 방법으로는
MyClass::Instance()->MyMethod();
이런식으로 사용하면 되겠습니다.

이런 방법을 사용하게 되니... 단순히 이 클래스를 하나만 정의해 두고, 내가 만든 클래스를 싱글톤 패턴으로 사용하고 싶을 때 이걸 상속해서 쓰면 되는게 편해지더군요. template방법이 어떨 땐 불편할 때도 있었는데.. 이걸 보니.. 좋은점도 있다는 생각이 듭니다.


'C / C++' 카테고리의 다른 글

Collaborative Filtering  (0) 2009.01.19
C++에서 XML 파일 읽기  (0) 2008.09.09
libcmtd.lib LNK2005 - 중복 선언 에러  (0) 2008.05.09
C++ 클래스 안에서 쓰레드를 생성해 쓰기  (0) 2008.02.28

#include <iostream>
using namespace std;

class Singleton
{
public:
 static Singleton& Instance();
 static Singleton* _Instance;

public:
 Singleton(){

 }
 Singleton(Singleton &single){
  _Instance = &single.Instance();
  cout << "복사 생성자" << endl;
 }
 ~Singleton(){

 }
};

Singleton *Singleton::_Instance = 0;
Singleton& Singleton::Instance()
{
 static Singleton obj;
 return obj;
}

int main()
{
 Singleton m = Singleton::Instance();
 return 0;
}

+ Recent posts