fragmentDispatchingAndroidInjector while using support fragments

霸气de小男生 提交于 2019-12-31 01:23:06

问题


I'm trying to create a simple dagger 2 application while using support v4 fragments. After I modified my application I got this strange compilation error

Error:(35, 8) error: [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> cannot be provided without an @Provides-annotated method.
java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> is injected at
dagger.android.DispatchingAndroidInjector.<init>(injectorFactories)
dagger.android.DispatchingAndroidInjector<android.support.v4.app.Fragment> is injected at
app.series.com.tvshowsapplication.ui.main.MainActivity.fragmentDispatchingAndroidInjector
app.series.com.tvshowsapplication.ui.main.MainActivity is injected at
dagger.android.AndroidInjector.inject(arg0)

After a quick search I found this link. It says I would need to use

The thing is I didn't understand where should I need to put this part

@Multibinds
abstract Map<Class<? extends android.app.Fragment>, AndroidInjector.Factory<? extends android.app.Fragment>> bindNativeFragments();

My guess I need to put it in BaseActivity because it's an abstract function, but how do I implement it in the main activity?

My MainActivity:

public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> implements MainNavigator, HasSupportFragmentInjector {

    @Inject
    ViewModelProvider.Factory mViewModelFactory;

    @Inject
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;

    private MainViewModel mMainViewModel;

    private DrawerLayout mDrawer;
    private Toolbar mToolbar;
    private NavigationView mNavigationView;
//    private SwipePlaceHolderView mCardsContainerView;

    ActivityMainBinding mActivityMainBinding;

    public static Intent getStartIntent(Context context) {
        Intent intent = new Intent(context, MainActivity.class);
        return intent;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivityMainBinding = getViewDataBinding();
        mMainViewModel.setNavigator(this);
        setUp();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mDrawer != null)
            mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    }

    public void onFragmentDetached(String tag) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = fragmentManager.findFragmentByTag(tag);
        if (fragment != null) {
            fragmentManager
                    .beginTransaction()
                    .disallowAddToBackStack()
                    .setCustomAnimations(R.anim.slide_left, R.anim.slide_right)
                    .remove(fragment)
                    .commitNow();
            unlockDrawer();
        }
    }

    private void setUp() {

        mDrawer = mActivityMainBinding.drawerView;
        mToolbar = mActivityMainBinding.toolbar;
        mNavigationView = mActivityMainBinding.navigationView;
//        mCardsContainerViewerView = mActivityMainBinding.cardsContainer;

        setSupportActionBar(mToolbar);
        ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(
                this,
                mDrawer,
                mToolbar,
                R.string.open_drawer,
                R.string.close_drawer) {
            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                hideKeyboard();
            }

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
            }
        };
        mDrawer.addDrawerListener(mDrawerToggle);
        mDrawerToggle.syncState();
        setupNavMenu();
        String version = getString(R.string.version) + " " + BuildConfig.VERSION_NAME;
        mMainViewModel.updateAppVersion(version);
        mMainViewModel.onNavMenuCreated();
//        setupCardContainerView();
        subscribeToLiveData();
    }

    private void subscribeToLiveData() {

    }



    private void setupNavMenu() {
        NavHeaderMainBinding navHeaderMainBinding = DataBindingUtil.inflate(getLayoutInflater(),
                R.layout.nav_header_main, mActivityMainBinding.navigationView, false);
        mActivityMainBinding.navigationView.addHeaderView(navHeaderMainBinding.getRoot());
        navHeaderMainBinding.setViewModel(mMainViewModel);

        mNavigationView.setNavigationItemSelectedListener(
                new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        mDrawer.closeDrawer(GravityCompat.START);
                        switch (item.getItemId()) {
//                            case R.id.navItemAbout:
//                                showAboutFragment();
//                                return true;
//                            case R.id.navItemRateUs:
//                                RateUsDialog.newInstance().show(getSupportFragmentManager());
//                                return true;
//                            case R.id.navItemFeed:
//                                startActivity(FeedActivity.getStartIntent(MainActivity.this));
//                                return true;
//                            case R.id.navItemLogout:
//                                mMainViewModel.logout();
//                                return true;
//                            default:
//                                return false;
                        }
                        return false;
                    }
                });
    }

//    private void showAboutFragment() {
//        lockDrawer();
//        getSupportFragmentManager()
//                .beginTransaction()
//                .disallowAddToBackStack()
//                .setCustomAnimations(R.anim.slide_left, R.anim.slide_right)
//                .add(R.id.clRootView, AboutFragment.newInstance(), AboutFragment.TAG)
//                .commit();
//    }

    private void lockDrawer() {
        if (mDrawer != null)
            mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    }

    private void unlockDrawer() {
        if (mDrawer != null)
            mDrawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    }


    @Override
    public void openLoginActivity() {
        startActivity(LoginActivity.getStartIntent(this));
        finish();
    }

    @Override
    public void handleError(Throwable throwable) {
        // handle error
    }

    @Override
    public MainViewModel getViewModel() {
        mMainViewModel = ViewModelProviders.of(this, mViewModelFactory).get(MainViewModel.class);
        return mMainViewModel;
    }

    @Override
    public int getBindingVariable() {
        return BR.viewModel;
    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        return fragmentDispatchingAndroidInjector;
    }
}

UPDATE

I actually added the module in the component class, here is my AppComponent

@Singleton
@Component(modules = {AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        Builder application(Application application);

        AppComponent build();

    }

    void inject(TVShowsApp app);

}

AppModule

@Module
public class AppModule {

    @Provides
    @Singleton
    Context provideContext(Application application) {
        return application;
    }


    @Provides
    @Singleton
    CalligraphyConfig provideCalligraphyDefaultConfig() {
        return new CalligraphyConfig.Builder()
                .setDefaultFontPath("fonts/source-sans-pro/SourceSansPro-Regular.ttf")
                .setFontAttrId(R.attr.fontPath)
                .build();
    }
}

and ActivityBuilder

@Module
public abstract class ActivityBuilder {

    @ContributesAndroidInjector(modules = MainActivityModule.class)
    abstract MainActivity bindMainActivity();

}

回答1:


You need to put it in a module that you then register in your Component, but you don't have to declare it manually, as Dagger already has the AndroidInjectionModule (or AndroidSupportInjectionModule with AppCompat) which you can use.

You can find more about the Android setup in the official documentation or see some additional information in a similar question about when you need to install the module that was asked quite recently.

You're not showing your AppComponent, but you most likely just forgot to add the module, so you can fix your error by adding it to your component.

// add it somehow like this
@Component(modules = { AndroidSupportInjectionModule.class, AppModule.class })
public interface AppComponent {
  void inject(App app);
}


来源:https://stackoverflow.com/questions/48482202/fragmentdispatchingandroidinjector-while-using-support-fragments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!