2016-10-27 15 views
0

前に読んだとおり、daggerはすべてのコンストラクタを生成して提供するため、事業内にコンストラクタはほとんど存在しません。Fragmentの中にRecyclerViewActivityは、私が働いているサンプルはhereあるAndroid、Dagger 2はフラグメント内にrecyclerviewを挿入します

私は LayoutManagerAdapterを注入しても Presenterフラグメントのために(活動の内側にそれらを注入することなく、フラグメントに引数を通過する)ことができますどのように、フラグメントを注入されたが、彼は Activityを使用しましたそれ自体はパターンによると Viewとして、私はを使用しようとしています代わりに10。

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は、このビューをそのコンストラクタに期待します。

第2のこととして、このモジュールでは、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); 
     // ... 
    } 

私が言ったように、これはそれを行う唯一の方法ではありません。これには、コンポーネントを何度も作成するという問題があります。コンポーネントをスコープする場合、それを正しく処理する必要があります。毎回作成することはできません。そうしないと、スコープが役に立たなくなります。問題があるのは、ビューを挿入するたびにモジュールが正しいビューを必要とすることです。モジュールがそのビューを参照していることを確認する必要があります。

これが役に立ちます。

EDIT

あなたのコードを見た後、私は問題はあなたがそう本質的な問題を解決する可能性がありますそう、注入する前にフラグメントを追加しているという事実と関連していると思います

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(fragment)) .inject(フラグメント);' – AlirezaXX

関連する問題