How to inject dependencies into any kind of object

2019-03-15 09:10发布

问题:

According to http://konmik.github.io/snorkeling-with-dagger-2.html i could just add

inject(Anything anything)

into AppComponent.java, but this doesn't work for me, in the articles example:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(MainActivity activity);
    void inject(MainFragment fragment);
    void inject(MainToolbarView view);
}

If I try to inject dependencies into my fragment the injected members remain null. What obvious error am I missing here?

Relevant sources:

ApplicationComponent.java

@Singleton
@Component(
    modules = ApplicationModule.class
)
public interface ApplicationComponent {
    void injectApplication(BaseApplication application);

    Prefs providePrefs();
}

ApplicationModule.java

@Module
public class ApplicationModule {
    private final Application application;

    public ApplicationModule(Application application) {
        this.application = application;
    }

    @Provides
    Application application() {
        return application;
    }

    @Singleton
    @Provides
    Prefs providePrefs() {
        return Prefs.with(application);
    }
}

ActivityComponent.java

@AScope
@Component(
    dependencies = {
        ApplicationComponent.class
    },
    modules = ActivityModule.class
)
public interface ActivityComponent extends ApplicationComponent {
    void injectActivity(BaseActivity activity);
    void injectFragment(BaseFragment fragment);
}

ActivityModule.java

@Module
public class ActivityModule {
    private final Activity activity;

    public ActivityModule(Activity activity) {
        this.activity = activity;
    }

    @Provides
    Activity activity() {
        return activity;
    }

    @Provides
    Context context() {
        return activity;
    }
}

BaseApplication.java

public class BaseApplication extends Application {
    private ApplicationComponent component;


    @Override
    public void onCreate() {
        super.onCreate();
        component = createComponent();

        component.injectApplication(this);
    }

    private ApplicationComponent createComponent() {
        return Dagger_ApplicationComponent.builder()
            .applicationModule(new ApplicationModule(this))
            .build();
    }

    public ApplicationComponent getComponent() {
        return component;
    }
}

BaseActivity.java

public class BaseActivity extends ActionBarActivity implements HasComponent<ActivityComponent> {
    ActivityComponent component;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        component = Dagger_ActivityComponent.builder()
            .applicationComponent(((BaseApplication) getApplication()).getComponent())
            .activityModule(new ActivityModule(this))
            .build();

        component.injectActivity(this);

    }

    @Override
    public ActivityComponent getComponent() {
        return component;
    }
}

BaseFragment.java

public class BaseFragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((BaseActivity)getActivity()).getComponent().injectFragment(this);
    }
}

ListFragment.java

public class ListFragment extends BaseFragment {

    @Inject ListFragmentPresenterImpl listFragmentPresenter;

    public static ListFragment newInstance(){
        ListFragment result = new ListFragment();

        return result;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        View rootView = inflater.inflate(R.layout.list_fragment, container, false);

        Log.d("",listFragmentPresenter.sayHello());  // NPE HERE

        return rootView;
    }
}

ListFragmentPresenterImpl.java

public class ListFragmentPresenterImpl implements ListFragmentPresenter {

    @Inject
    public ListFragmentPresenterImpl() {
    }

    @Override
    public String sayHello() {
        return "hello";
    }
}

In Dagger_ActivityComponent the generated code looks like this:

@Override
public void injectActivity(BaseActivity activity) {  
  baseActivityMembersInjector.injectMembers(activity);
}

@Override
public void injectFragment(BaseFragment fragment) {  
  MembersInjectors.noOp().injectMembers(fragment);
}

shouldn't here be a baseFragmentMemebersInjector?

Thanks!

回答1:

Inject child fragments instead of BaseFragment. In your case:

public class ListFragment extends BaseFragment {

    @Inject ListFragmentPresenterImpl listFragmentPresenter;

    public static ListFragment newInstance(){
        ListFragment result = new ListFragment();
        return result;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((MainActivity)getActivity()).getComponent().injectFragment(this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View rootView = inflater.inflate(R.layout.list_fragment, container, false);
        Log.d("",listFragmentPresenter.sayHello());  // NPE HERE
        return rootView;
    }
}

And in your Component class:

@AScope
@Component(dependencies = ApplicationComponent.class,
           modules = ActivityModule.class)
interface ActivityComponent {
    void injectActivity(MainActivity activity);
    void injectFragment(ListFragment fragment);
    // Put any more injects here, if BaseFragment has
    // any other children that need to be injected, for example:
    void inject(MapFragment fragment);
    void inject(DetailFragment fragment);
}

Parent -> Child injection is not working in Dagger 2. It was covered here, here and this SO question.