이클립스 프로젝트에 RoboGuice(RG) 2.0 설치하기

- 안드로이드프로젝트의 libs에 roboguice-2.0.jar, guice-3.0-no_aop.jar, javax.inject-1.jar 파일을 넣고 빌드패스에 추가

- RG 2.0에서는 RoboApplication 상속받은 Application을 작성해서 AndroidManifest.xml에 등록할 필요는 없음

  


Activity 작성

- RoboActivity 상속받은 Activity 작성

- @InjectView , @Inject 등의 어노테이션 사용



모듈 주입 커스터마이징

- AbstractModule 클래스를 상속받는 클래스 작성

- configure() 메소드에서 커스텀 바인딩 정의 : 자세한 구현은 Google Guice 문서 참조

- res/values/roboguice.xml에 아래처럼 컴스텀 모듈 등록


<?xml version="1.0" encoding="utf-8"?>

  <resources> 

    <string-array name="roboguice_modules">

    <item>com.mypackage.MyModule</item>

  </string-array>

</resources>




인스턴스 스코프

RG에 의해 생성 및 관리되어 다른 클래스에 주입되는 클래스의 인스턴스 스코프(생명주기) 설정


1. Singleton 스코프

- 앱에서 하나의 인스턴스만 존재

- 클래스에 @Singleton 어노테이션 선언 : Guice에서 제공

- 어떤 클래스에서 이 객체를 요청하든 동일한 인스턴스가 제공됨. 그러므로 쓰레드세이프하게 작성해야 함.

- Application 컨텍스트는 직접 주입 받을 수있음(특정 Activity, Service 등 current context랑 관계없는 global context)

- current context(액티비티 컨텍스트)를 주입받으려면 Provider<Context>를 사용해야 함

- 싱글턴 스코프를 가진 기본제공 모듈 : Application, ViewListener, Resources 등?

=> 그러나 RG에서 제공하는 대부분의 모듈은 context를 필요로 하므로 ContextSingleton 스코프를 갖는다.

- current context가 필요없거나 또는 Application 컨텍스트만 필요한 클래스에 적합


2. ContextSingleton 스코프

- current context(액티비티 컨텍스트)에 대해서 하나의 인스턴스만 존재

- 클래승 @ContextSingleton 어노테이션 선언 : RG에서 제공하는 스코프

- current context가 필요한 클래스는 ContextSingleton으로 선언

- 동일 액티비티 객체에 대해서 동일 인스턴스 제공(모든 액티비티에 대해서 동일 인스턴스 제공은 아님)

- Application, Context, Activity, Service 등 @Singleton/@ContextSingleton 클래스를 직접 주입받을 수 있음

- 컨텍스트싱글턴 스코프를 가진 기본제공 모듈 : Context, Activity, Service, AssetManager, ContentResolver,

   LayoutInflator 및 기타 시스템서비스 모듈들

- current context가 필요한 클래스에 적합


3. 프로토타입 스코프

- 요청할 때마다 새로운 인스턴스 생성

- 클래스에 별도의 스코프 어노테이션 선언 없음. (프로토타입이란 용어는 제가 스프링에서 따온 것임)

- 주입될 때마다 또는 provider.get() 할 때마다 새 인스턴스가 생성됨

- 스코프가 설정돼있지 않고 public 기본생성자가 존재하는 모든 클래스가 가능

- Handler처럼 Provider에서 get() 요청시마다 새로운 인스턴스를 리턴하는 클래스

- context가 필요없고 상태를 가진 클래스에 적합


스코프 지정 방법

 (1) 구현체 클래스에 @Singleton 붙임

 (2) @Provides 붙은 메소드에 @Singleton 붙임

 (3) bind().xxx().in(Singleton.class);


주요 기본제공 클래스의 스코프

http://code.google.com/p/roboguice/wiki/ProvidedInjections



어떤 컨텍스트를 주입받을 것인가 

- http://code.google.com/p/roboguice/wiki/InjectingContexts

- current context가 필요한게 아니라면 명시적으로 Application을 주입받아라

- Activity가 필요하다면 Activity를 주입받아라

- 잘 모르겠으면 Context를 주입받아라



Inject 되기 위한 생성자 조건

- 기본 생성자가 존재하거나 

- Inject가능한 파라미터로만 구성되고 @Inject 선언된 생성자가 존재


  @Inject

  SomeClass(Context context, MyComponent component) {}

  // 여기서 context와 component는 inject 가능해야함...



일반 POJO 클래스에 다른 객체들을 주입하는 방법

1. POJO 생성을 RG가 처리하는 경우 

- POJO 내부의 @Inject로 선언된 멤버들은 자동 주입됨

- POJO 클래스가 RoboActivity를 상속받는 액티비티의 @Inject 멤버변수로 선언돼있는 경우 등


2. POJO 생성을 RG가 처리하지 않는 경우(개발자 또는 라이브러리에서 직접 생성하는 경우)

- POJO 생성자 등에서 RoboGuice.injectMembers(context, this)를 이용하여 수동으로 주입함



명시적인 injector 사용을 피하는 방법(생성자 등 초기화 메소드를 핸들링할 수 없는 경우)

- 클래스 또는 Provider, ContextScopedProvider를 static하게 inject 받음

- http://code.google.com/p/roboguice/wiki/HowToInjectXYZ

 

 @Inject protected static ContextScopedProvider<T> tProvider; // T는 @ContextSingleton이어야함

 @Inject protected static ExceptionHandler;//singleton


=> 단, MyModule에서 requestStaticInjection(POJO.class)을 해주어야 함

=> 그러나 RG 2.0에서는 static injection을 비권장 ( http://code.google.com/p/roboguice/wiki/UpgradingTo20 )

=> static injection은 context에 액세스할 수 없는 클래스 및 static 메소드를 가진 헬퍼나 유틸 클래스에 적합할 듯.

(http://www.rosscode.com/blog/index.php?title=android-development-part-3-wiring-up-roboguice&more=1&c=1&tb=1&pb=1 )



Provider란 무엇인가

- 인스턴스 생성이 복잡한 경우 인스턴스를 만드는 방법을 제공

- 예를들어 new MyPojo()로 객체 생성후 myPojo.init() 등의 추가 작업한 인스턴스를 리턴

- MyPojo를 주입받는 모듈은 초기화 완료된 MyPojo 인스턴스를 받게 됨

- Module에서 @Provides 어노테이션을 쓰는 메소드를 작성해도 됨(Provider 인터페이스 구현안해도 됨)

- http://code.google.com/p/google-guice/wiki/ProvidesMethods




명시적/묵시적 바인딩

- 명시적 바인딩 : Module에서 bind().to(), bind().toProvider()로 바인딩하는 것

- 묵시적 바인딩 : 

   (1) 기본생성자나 inject가능한 생성자를 가진 구현 클래스가 존재하는 경우

   (2) @ImplementedBy를 통해 기본 구현체를 지정한 경우

   (3) @ProvidedBy를 통해 구현체 인스턴스를 생성해줄 Provider를 지정한 경우



AOP 애스펙트에도 RG의 inject가 가능한가

- 가능함. Aspects.aspectOf()를 통해 aspect 싱글턴을 구하여 Guice 모듈에서 강제 inject시켜줌.



Injection 이후에 지정된 메소드 호출

- Guice의 TypeListener를 이용하거나 GuiceyFruit 또는 MyciaGuice의 @PostConstruct를 사용

- http://stackoverflow.com/questions/2093344/guice-call-init-method-after-instantinating-an-object

- http://code.google.com/p/mycila/wiki/MycilaGuice

- http://code.google.com/p/guiceyfruit/




* 참고

RoboGuice 2.0 설정 방법 : http://code.google.com/p/roboguice/wiki/UpgradingTo20


Posted by 에코지오
,

1. RoboGuice 2.0

- RoboActivity의 onContentChanged() 메소드에서 View 주입(inject)


    @Override

    public void onContentChanged() {

        super.onContentChanged();

        RoboGuice.getInjector(this).injectViewMembers(this); //View 주입

        eventManager.fire(new OnContentChangedEvent());

    }



2. AndroidAnnotations 2.5

- 언더바 붙은 Activity(Java Annotation Processing에 의해 생성)의 setContentView() 메소드에서 View 주입 및 @Click 처리


    @Override

    public void setContentView(int layoutResID) {

        super.setContentView(layoutResID);

        afterSetContentView_();

    }



    private void afterSetContentView_() {

        //View 주입 코드

        mSaveBtn = ((Button) findViewById(id.save_btn)); 

        // ... ...


        // @Click 처리 코드

        {

            View view = findViewById(id.save_btn);

            if (view!= null) {

                view.setOnClickListener(new OnClickListener() {



                    public void onClick(View view) {

                        save();

                    }


                }

                );

            }

        }

        //... ...


        init();

        //... ...

    }


Posted by 에코지오
,

RoboGuice 2.x 사용 환경에서 ProGuard 설정에 추가해줄 내용입니다.

(참고 : http://code.google.com/p/roboguice/wiki/ProGuard)


# res/values/roboguice.xml 파일에 풀네임이 지정되는 클래스 보존

-keep class * extends com.google.inject.AbstractModule


# 참조할 수 없다는 경고 제거(can't find referenced method)

-dontwarn roboguice.**


# roboguice,guice 클래스 및 멤버 보존(필요에 따라 좀더 세밀하게 조정할 것)

-keep class roboguice.event.EventThread { *; }

#-keep public class roboguice.**

#-keep public class com.google.inject.**


# @Inject 붙은 생성자/필드/메소드 및 public 기본생성자 보존

-keepclassmembers class * {

    @com.google.inject.Inject <init>(...);

    @com.google.inject.Inject *;

    public <init>();

}


# There's no way to keep all @Observes methods, so use the On*Event convention to identify event handlers

-keepclassmembers class * {

    void *(**On*Event);

}

Posted by 에코지오
,