2016-10-27 8 views
0

이전에 읽었던 것처럼 대거는 모든 생성자를 내 보내고 제공하므로 사업 내에서 거의 모든 생성자가 없어야합니다. 이제 Fragment 안에 RecyclerView이 있고, Activity 내가 (활동 내부를 주입없이 조각에 인수 통과) LayoutManagerAdapter과 조각에도 Presenter를 주입 나는이 here을 일하고 있어요안드로이드, Dagger 2는 프래그먼트 안에 recyclerview를 삽입합니다.

샘플을 수있는 방법, 조각을 주입하지만, 그는 Activity을 사용 자체는 패턴에 따라 View이지만 사용하려고 시도하고 있습니다 Fragment 대신.

This은 그의 사람 Activity입니다 (리사이클 러 뷰와 발표자는 여기에 주입됩니다).

내 코드 :

UserComponent

@UserScope 
@Subcomponent(modules = UserModule.class) 
public interface UserComponent { 
    RepoListComponent plus(RepoListModule repoListModule); 

    UserEntity getUserEntity(); 
} 

RepoListModule AppComponent의 하위 구성 요소입니다 :

@Module 
public class RepoListModule { 
private RepoListContract.View view; 

public RepoListModule(RepoListContract.View view) { 
    this.view = view; 
} 

@Provides 
RepoListContract.View provideRepoListContractView(){ 
    return view; 
} 

@Provides 
LinearLayoutManager provideLayoutManager(Context context) { 
    return new LinearLayoutManager(context); 
} 

@Provides 
RepoListAdapter provideAdapter(RepoListContract.View view) { 
    return new RepoListAdapter(view); 
    } 
} 

RepoListComponent :

@Subcomponent(modules = RepoListModule.class) 
public interface RepoListComponent { 
    void inject(RepoListContract.View view); 
} 

RepoListActivity :

public class RepoListActivity extends BaseActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_repo_list); 
    RepoListFragment fragment = (RepoListFragment) getSupportFragmentManager() 
      .findFragmentById(R.id.fragment_container); 
    if (fragment == null) { 
     fragment = new RepoListFragment(); 
     ActivityUtils.addFragmentToActivity(getSupportFragmentManager(), 
       fragment, R.id.fragment_container); 
    } 
    GApplication.get(getApplicationContext()) 
      .getUserComponent().plus(new RepoListModule(fragment)) 
      .inject(fragment); 
    } 
} 

RepoListFragment : "... 그래서 우리는 우리의 사업 안에 거의 모든 생성자를하지 말았어야 ..."나는 완전히이 말을 이해한다면

public class RepoListFragment extends Fragment implements RepoListContract.View { 
@BindView(R.id.rv_repo) RecyclerView rvRepo; 

@Inject RepoListContract.Presenter presenter; 
@Inject LinearLayoutManager layoutManager; 
@Inject RepoListAdapter adapter; 

public static RepoListFragment newInstance() { 
    return new RepoListFragment(); 
} 

@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 
         @Nullable Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_repo_list, container, false); 
    ButterKnife.bind(this, v); 
    initRvRepo(); 
    return v; 
} 
private void initRvRepo() { 
    rvRepo.setLayoutManager(layoutManager); // null 
    rvRepo.setAdapter(adapter); //null 
} 

@Override 
public void onResume() { 
    super.onResume(); 
    presenter.subscribe(); //NullPointerException 
    } 
} 

답변

2

는 잘 모르겠어요. 보통 나는 들른다 - 당신이 new 연산자를 볼 때마다 엄지 손가락의 규칙으로 인스턴스화되는 클래스에 대한 긴밀한 의존성이 있음을 나타내는 것이므로이를 제거해야한다. 즉, 여기에 내가 당신의 과제에 접근하는 방법이 있습니다 (분명히 더 많은 해결책이 있습니다, 이것은 하나의 접근법입니다).

가장 간단한 것부터 시작해 보겠습니다. 의 당신의 조각을 만들어 보자 :

public RepositoriesListFragment extends Fragment implements RepositoriesListView { 
    @Inject RecyclerView.LayoutManager layoutManager; 
    @Inject RecyclerView.Adapter adapter; 
    @Inject RepositoriesListPresenter presenter; 

    public static RepositoriesListFragment newInstance() { 
     return new RepositoriesListFragment(); 
    } 
    // ... 
} 

지금이 종속성에 대한 모듈 수 : 주목해야 할

@Module 
public class RepositoriesListModule { 
    private final RepositoriesListView view; 

    public RepositoriesListModule(RepositoriesListView view) { 
     this.view = view; 
    } 

    @Provides 
    public RepositoriesListView providesView() { 
     return view; 
    } 

    @Provides 
    public RecyclerView.LayoutManager providesLayoutManager(Context context) { 
    return new LinearLayoutManager(context); 
    } 

    @Provides 
    public RecyclerView.Adapter providesAdapter(SomeAdapterImpl adapter) { 
    return adapter; 
    } 

    @Provides 
    public RepositoriesListPresenter providesPresenter(SomePresenterImpl presenter) { 
     return presenter; 
    } 
} 

우선이 생성자에서보기를 기대하고 있다는 것입니다. 일반적으로 발표자는보기가 필요하기 때문에 여기에 있습니다. 따라서 SomePresenterImpl은 생성자에서이 뷰를 기대합니다.

두 번째로,이 모듈은 어딘가에서 Context을 제공한다고 가정합니다. 구성 요소가 의존하는 다른 모듈을 통해 가능성이 가장 높습니다.

는 다음 구성 요소의 :

@Component(modules = { RepositoriesListModule.class, ... }) 
public interface RepositoriesListComponent { 
    void inject(RepositoriesListFragment fragment); 
} 

(이 구성 요소가 다른 모듈을 필요로하거나 다른 구성 요소에 의존 할 수 전에 말했듯이).

마지막으로해야 할 일은 조각을 삽입하는 것입니다. 당신이 말했듯이, 단편을 만들고 주입하는 활동이 있습니다. 그래서 이것은 다음과 같이 보일 수 있습니다 :

public class MainActivity extends Activity { 
    public void onCreate(Bundle savedInstanceState) { 
     // ... 
     RepositoriesListFragment fragment = RepositoriesListFragment.newInstance(); 

     DaggerRepositoriesListComponent.builder() 
     .repositoriesListModule(new RepositoriesListModule(fragment)) 
     .inject(fragment); 
     // ... 
    } 

내가 말했듯이,이 방법을 사용하는 것이 아닙니다. 여기에는 구성 요소를 여러 번 만드는 문제가 있습니다. 구성 요소를 범위 지정하는 경우 올바르게 처리해야합니다. 매번 생성 할 수는 없습니다. 그렇지 않으면 스코프가 쓸모 없게됩니다. 어려운 부분은 뷰를 삽입 할 때마다 모듈이 올바른 뷰를 필요로한다는 것입니다. 모듈이 뷰를 참조하는지 확인해야합니다.

희망이 도움이됩니다.

편집 :

:

당신의 코드를 살펴 후에 나는 문제가 당신이 그렇게 근본적으로 문제를 해결할 수있는 그렇게, 주입하기 전에 조각을 추가하고 있다는 사실과 관련이있다 생각

public class RepoListActivity extends BaseActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_repo_list); 
    RepoListFragment fragment = (RepoListFragment) getSupportFragmentManager() 
     .findFragmentById(R.id.fragment_container); 
    if (fragment == null) { 
     fragment = new RepoListFragment(); 
     GApplication.get(getApplicationContext()) 
     .getUserComponent().plus(new RepoListModule(fragment)) 
     .inject(fragment); 
     ActivityUtils.addFragmentToActivity(
      getSupportFragmentManager(), 
      fragment, R.id.fragment_container); 
    } 
    } 
} 

왜 그런가? RepoListFragment을보고 onResumeonCreateView에있는 주입 변수에 액세스하고 있습니다. 이것은 액티비티에 추가 된 조각의 라이프 사이클의 일부입니다 (ActivityUtils.addFragmentToActivity이 실제로 레이아웃의 조각을 추가/대체한다고 가정).

회원님이 볼 수 있듯이, 회원을 추가 할 기회가 있기 전에 이미 회원들에게 액세스하고 있습니다. 따라서 조각을 추가하기 전에 삽입해야합니다.

+0

예를 들어 내가 어댑터에 액세스 할 수 있다는 말씀입니까? 나는 그랬지만 작동하지 않았다. – AlirezaXX

+0

당신은 어댑터에 접근한다는 것은 무엇을 의미 하는가? 당신은 스스로 어댑터를 생성합니다 ... – Fred

+0

완전한 응답을 주셔서 감사합니다. 그러나 'RepositoriesListComponent'는 AppComponent의 하위 구성 요소 인 UserComponent의 하위 구성 요소이므로, 어댑터와 layoutManager가 null이 될 수 있습니다. -> 활동 : => 'GApplication.get (getApplicationContext()) .getUserComponent(). plus (새 RepoListModule (조각)) .inject (조각);' – AlirezaXX

관련 문제