Dagger2 시작하기 (Java) part3- @Singleton

TPark·2020년 6월 24일
0

안드로이드

목록 보기
8/10
post-custom-banner

@Singleton

@Singleton 어노테이션은 Dagger2가 해당 객체를 제공할때 단 하나의 인스턴스만 만들수 있도록 한다.

사용하는 방법은 간단하다. 싱글턴 패턴을 적용하고자 하는 객체 클래스에 @Singleton 어노테이션을 붙히거나 @Provides 혹은 @Binds 메소드에 @Singleton 어노테이션을 붙힌 뒤 해당 컴포넌트 클래스에 @Singleton 어노테이션을 붙혀주면 된다.

예제

@Singleton
public class Driver {
    @Inject
    public Driver(){}
}

@Module
public class DieselEngineModule {
    @Singleton
    @Provides
    static Engine provideEngine(DieselEngine engine) {
        return engine;
    }
}

@Singleton
@Component(modules = {WheelsModule.class, DieselEngineModule.class})
public interface CarComponent {
    void inject(MainActivity activity);

    @Component.Builder
    interface Builder {
        CarComponent build();

        @BindsInstance
        Builder horsePower(@Named("horse power") int horsePower);

        @BindsInstance
        Builder engineCap(@Named("engine capacity") int engineCap);

        @BindsInstance
        Builder airPressure(@Named("air pressure") int airPressure);
    }
}

public class Car {
    private static final String TAG = "Car";

    private Driver driver;
    private Engine engine;
    private Wheels wheels;

    @Inject
    public Car(Engine engine, Wheels wheels, Driver driver) {
        this.engine = engine;
        this.wheels = wheels;
        this.driver = driver;
    }

    public void drive() {
        Log.d(TAG, "driving..." + this + ", driver is : " + driver);
    }
}

public class MainActivity extends AppCompatActivity {
    @Inject
    public Car car1;
    @Inject
    public Car car2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        CarComponent component = DaggerCarComponent.builder()
                .horsePower(20)
                .engineCap(100)
                .airPressure(500)
                .build();
        component.inject(this);
        car1.drive();
        car2.drive();
    }
}

Result

driving...com.example.dagger2tutorial.car.Car@8f96006, driver is : com.example.dagger2tutorial.car.Driver@813e6c7, engine is: com.example.dagger2tutorial.car.DieselEngine@5b414f4

driving...com.example.dagger2tutorial.car.Car@4c7741d, driver is : com.example.dagger2tutorial.car.Driver@813e6c7, engine is: com.example.dagger2tutorial.car.DieselEngine@5b414f4

car1, car2의 인스턴스가 다른 반면에 같은 DieselEngine과 Driver 인스턴스를 공유하는 걸 볼수있다.

Application 레벨에서 컴포넌트 선언하기

지금까지 시리즈의 예제에서는 액티비티에서 컴포넌트를 선언해서 사용했다. 이렇게 사용했을때 생길 수 있는 문제 중 하나가 화면이 회전되거나 윈도우 사이즈가 변경되는 등의 이유로 액티비티가 디스트로이 된후 새로 생성되었을때 싱글턴 패턴을 유지하지 못 한다는 문제가 있다.

예를 들어, 위 예제에서 앱의 화면을 회전시켜보자.

결과

D/Car: driving...com.example.dagger2tutorial.car.Car@92013e4, driver is : com.example.dagger2tutorial.car.Driver@f10204d, engine is: com.example.dagger2tutorial.car.DieselEngine@c436702

회전 시키기 전의 Driver 인스턴스 (Driver@813e6c7)와 다른 인스턴스임을 볼수 있다.

이 문제를 해결하려면 컴포넌트가 애플리케이션 사용 내내 살아있을 수 있도록 해야한다. 이를 위해 Application을 상속하는 Custom Application 클래스를 만든 뒤, 그 안에서 컴포넌트를 선언해서 사용해야 한다.

예제

public class MyApplication extends Application {
    private CarComponent component;
    @Override
    public void onCreate() {
        super.onCreate();

        component = DaggerCarComponent.builder()
                .airPressure(100)
                .engineCap(200)
                .horsePower(300)
                .build();
    }

    public CarComponent getComponent() {
        return component;
    }
}

public class MainActivity extends AppCompatActivity {
    @Inject
    public Car car1;
    @Inject
    public Car car2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        CarComponent component = ((MyApplication) getApplication()).getComponent();
        component.inject(this);
        car1.drive();
        car2.drive();
    }
}

추가로 MyApplication을 사용하려면 Manifest 파일의 Application scope에 android:name=".MyApplication"를 추가해줘야 한다.

결과

회전하기 전
D/Car: driving...com.example.dagger2tutorial.car.Car@8f96006, driver is : com.example.dagger2tutorial.car.Driver@813e6c7, engine is: com.example.dagger2tutorial.car.DieselEngine@5b414f4

회전 후
D/Car: driving...com.example.dagger2tutorial.car.Car@136c2ec, driver is : com.example.dagger2tutorial.car.Driver@813e6c7, engine is: com.example.dagger2tutorial.car.DieselEngine@5b414f4

싱글턴 패턴을 적용한 Driver와 DieselEngine의 인스턴스가 회전 후에도 같은 인스턴스 임을 확인할 수 있다.

참조

https://www.youtube.com/playlist?list=PLrnPJCHvNZuA2ioi4soDZKz8euUQnJW65

post-custom-banner

0개의 댓글