[번역]System Services는 System만의 것이 아니다.
Dagger와 Custom View를 사용하면서 흥미로운 동작을 마주쳤다. 대부분의 경우, 나의 앱은 2개의 Component를 가진다. 싱글톤을 위한 최상위 레벨 AppComponent와 “Activity당 하나”이여야 하는 다른 것들을 위한 Activity Component가 있다. 나의 Activity들 안에는 일반적인 Dagger의 boilerplate가 존재한다:
activityComponent = application.getAppComponent()
.plusActivityComponent(new ActivityModule(this));
추가적으로 나는 activity component를 getter로 노출하는 것을 선호한다. 그래서 View들은 activity scoped 객체에 접근할 수 있다:
public interface ActivityComponentProvider {
Activitycomponent getActivityComponent();
}
View안에서는 이렇게 할 수 있다:
public VrView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(getContext(), R.layout.vr_view_contents, this);
((ActivityComponentProvider)context)
.getActivityComponent().inject(this);
...
대부분의 경우 이는 잘 동작한다. 하지만 어제는 대부분의 경우에 해당하지 않았다. 이 글은 내가
@Override
public Object getSystemService(String name) {
return super.getSystemService(name);
}
context.getSystemService
은 보통 LayoutInflator
같은 것들을 참조하기 위해 사용된다. 당신의 activity에 이 메소드를 오버라이드하면, 이제 당신은 특정 키를 사용하여 당신이 원하는 어떠한 인스턴스라도 돌려받을 수 있게 된다. 우리의 경우에는 Activity component를 돌려받기를 원한다.
@Override
public Object getSystemService(String name) {
if("Dagger".equals(name)){
return activityComponent;
}
return super.getSystemService(name);
}
만약 우리가 원하는 키가 아닌 경우 super로 호출을 해야함을 주의하라.
이제 getContext().getSystemService(key)
의 호출을 통해 view의 생성자 내부에서 activity component에 접근할 수 있다. 이 설정의 멋진 점은 context에서 activity를 찾기 위해 당신이 쌓여진 것들을 벗길 필요 없이, 당신을 위해 시스템이 이를 해줄 것이라는 것이다.
public VrView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(getContext(), R.layout.vr_view_contents, this);
ActivityComponent activityComponent = (ActivityComponent) getContext().getSystemService("Dagger");
activitycomponent.inject(this);
getContext
를 당신의 activity로 캐스트하는 위험 대신, 당신은 안드로이드 시스템 서비스 아키텍처를 지렛대로 사용할 수 있다.
마지막으로 Android Studio의 lint를 행복하게 만들기 위해
ActivityComponent activityComponent = (ActivityComponent) getContext().getSystemService("Dagger");
위에
//noinspection ResourceType
을 추가하라.
이것이 다다! 당신은 이제 view에서 당신의 activity component의 참조를 얻을 수 있다. 보너스: 비슷한 방식으로 당신은 Application 클래스의 getSystemService
를 오버라이드하고 여기서 app component를 전달할 수 있다. 이는 당신이 당신의 Activity에서 다음과 같은 것을 할 수 있게 해줄 것이다.
AppComponent component = (AppComponent) getAppplicationContext().getSystemService("AppComponent");
Thanks again to those that helped me grok this yesterday.