2017-11-23 3 views
0

Reprository : - 다음 TasksModule에서 , 내가 다른를 추가 할 https://github.com/googlesamples/android-architecture대거 범위 충돌

지점 잭-MVP-단검

이 TaskFragment가 contructorinjection

예를 들어

를 사용하여 주입되는 것을 알 수있다 TaskFragment의 필드 주입을위한 작업 조각을위한 모듈

@Module 
class TasksModule{ 
     @Fragmentscoped 
     @contributesandroidinjector(modules = AnotherModule.class) 
     abstract TasksFragment tasksFragment(); 
} 

@Module 
public class AnotherModule { 

    @Provides 
    @FragmentScoped 
    static Calendar getCalendar() { 
     return Calendar.getInstance(); 
    } 

} 


@activityscoped 
public class TasksFragment extends DaggerFragment implements TasksContract.View { 
    @Inject 
    Calendar calendar;//Field injection 

    @Inject 
    TasksFragment(){ 
    } 
} 

활동 :

Error:(34, 8) error: [dagger.android.AndroidInjector.inject(T)] java.util.Calendar cannot be provided without an @Provides- or @Produces-annotated method. 
java.util.Calendar is injected at 
com.example.android.architecture.blueprints.todoapp.tasks.TasksFragment.calendar 
dagger.Lazy<com.example.android.architecture.blueprints.todoapp.tasks.TasksFragment> is injected at 
com.example.android.architecture.blueprints.todoapp.tasks.TasksActivity.taskFragmentProvider 
com.example.android.architecture.blueprints.todoapp.tasks.TasksActivity is injected at 
dagger.android.AndroidInjector.inject(arg0) 
A binding with matching key exists in component: com.example.android.architecture.blueprints.todoapp.tasks.TasksModule_TasksFragment.TasksFragmentSubcomponent 

내가 주입에 관한 여기 아무것도 실종 :

public class TasksActivity extends DaggerAppCompatActivity { 

    @Inject 
    Lazy<TasksFragment> taskFragmentProvider; 


.... 
} 

내가 같은 오류는 무엇입니까?

+0

[귀하의 다른 질문] (https://stackoverflow.com/q/47444206/1426891)의 후속 조치로서이 코드에는 더 구체적인 코드가 있지만 "가능한가요?" 우리가 당신의 코드를 시도했는지 여부. 너? 오류 메시지가 나타 납니까? –

+0

내 질문을 업데이트했습니다. 제안 해 주셔서 감사합니다. –

+0

아! 훨씬 나아 졌어, 고마워. 내가 대답하기 전에, 당신이 TasksFragment activity-scoped를 만들었던 이유가 있습니까? fragment-scoped가 아니거나 완전히 unscoped입니까? –

답변

2

질문에 직접 답하려면 분명히 ActivityComponent에서 TasksFragment를 인스턴스화하려고합니다. 그러나 dagger.android가 생성 한 프래그먼트 특정 하위 구성 요소 내에서 @FragmentScoped 범위의 달력을 바인딩했습니다. 이것은 캘린더가 귀하의 프래그먼트 (및 귀하의 프래그먼트가 액세스하는 다른 객체) 내에서만 사용할 수 있으며 귀하의 액티비티 내에서는 사용할 수 없음을 의미합니다.

올바른 범위와 주입 구성 요소를 원하면 조각 이름 구성 요소를 사용합니다. 조각 구성 요소는 생성 된 이름과 조각 생성 방법이 없습니다. 이런 식으로 설계된 것은 아닙니다.

쉬운 대답 : 여기 생성자 주입에 의존하지 마십시오. Fragment에서 new으로 전화해야합니다. Android가하는 일이기 때문입니다. 특히이 목적으로 you are required to have a public parameterless constructor을 사용하고 있으며 Android는 제작시 조각을 삽입하지 않습니다. 여기에 생성자 삽입과 필드 주입에 대한 특별한 단검 규칙은 없지만, 이것은 안드로이드 시스템의 제약 조건이며 Fragment 인스턴스를 다시 생성 할 수있는 능력입니다.

대신 DaggerFragment를 확장하면 올바른 방법이며 dagger.android가 설계된 방식 인 instructing Dagger to inject your Fragment in its onAttach method이됩니다. 수동으로 또는 자동으로 Fragment를 삽입한다면 Fragment가 첨부 될 때 @Inject 필드가 대체되고 재 주입됩니다 ... Fragment는 Android가 자동으로 객체를 생성하는지 여부에 따라 다른 동작을합니다. 너 스스로 그렇게하든.

기타 사항 :

  • 그것은 당신의 조각이 부착 될 때마다 단검이 구성 요소의 새 인스턴스를 만들 것이기 ​​때문에, @FragmentScoped와 조각 자체를 주입하는 것이 중요하지, 그리고 당신의 조각의 의존성 중 하나가 주입 경우 TasksFragment dagger.android가 생성하는 Subcomponent.Builder에 바인드 된 인스턴스로 인해 올바른 Fragment 인스턴스를 가져옵니다.
  • 제공자로 @Inject Lazy<TasksFragment> taskFragmentProvider을 참조하지 마십시오. 일반적으로 Provider과 달리 Lazy은 객체가 범위가 없어도 항상 동일한 인스턴스를 반환합니다.
  • Fragment를 생성하고 연결하기 전에 Fragment와 상호 작용할 수 있지만, Fragment의 인스턴스 인수가 포함 된 assign it a Bundle이 필요합니다.이를 통해 안드로이드는 객체를 생성하고 다시 만드는 데 필요한 융통성을 갖게되고 onAttach 메서드에 번들을 제공합니다.이 번들 인수를 사용하면 삽입 된 객체에 대한 전체 액세스 권한을 사용할 수 있습니다.
+0

답변 해 주셔서 감사합니다. 그러나 귀하의 대답에 대한 혼란은 단도가 동일한 생성자를 사용하여 안드로이드가 조각을 인스턴스화하는 데 사용한다는 것입니다. 그래서 주된 차이점은 무엇입니까/충돌은 여기서 발생합니까? –

+1

Dagger가'@ Inject' 생성자를 호출 할 때, 다른 대문자와 마찬가지로'@Inject' 필드를 채우고'@Inject' 메소드를 호출하려고 시도합니다. 위에서와 같이 Activity 구성 요소에 Fragment를 삽입하도록 요청하면 문제가됩니다. dagger.android가 만드는 Fragment 구성 요소가 올바른 구성 요소이며 Fragment의 팩토리로 생성되거나 작동하도록 설계되지 않았습니다. 비록 쉽다해도 Fragment 인스턴스의 onAttach가 항상 삽입되어 항상 올바른 구성 요소를 사용하기 때문에 이것은 불필요한 작업입니다. –

+0

여기서 Lazy 변수를 사용하기 때문에, fragment 인스턴스는 lazy.get() 메소드가 호출 될 때까지 생성되지 않습니다 (생성자 삽입). 조각 주입기가 그 조각을 활동에 붙일 때까지 현장 주사는 일어나지 않을 것입니다. 그래서 프래그먼트를 액티비티에 붙이기 전에 프래그먼트가 이미 붙어 있는지 여부를 체크 할 것입니다. (실제 필드 인젝션을 제한합니다.) –

관련 문제