Kamajabu
Kamajabu

Reputation: 506

Dagger2 getting instance of activity presenter in fragment presenter

I'm really lost and hope you can help me. I'm programming app using MVP and dagger2. One of activities (let's say A ) contains fragments ( B ) in FragmentStatePagerAdapter. Both activity and fragments have their own presenters. I'm handling input in fragments ( B ), and transfer data from it "up" to main presenter ( B -> A ) (of activity holding fragments) and there ( A ) I'm handling network connection.

For this I need instance of main presenter ( A ) in fragment presenter ( B ). I've tried to use dependency on fragment graph but instead of getting already existing instance of presenter it's creating new one with every init. Any advises how I could get something similar to singleton but using ActivityScope?

A graph:

@ActivityScope
@Component(modules = GiftListModule.class, dependencies = AppGraph.class)
public interface GiftListGraph extends AppGraph{
    void inject(GiftListActivity giftListActivity);

    GiftListPresenter getGiftListPresenter();

    final class Initializer {
        public static GiftListGraph init(AppGraph appGraph, GiftListView giftListView) {
            return DaggerGiftListGraph.builder()
                                   .giftListModule(new GiftListModule(giftListView))
                                   .appGraph(appGraph)
                                   .build();
        }
    }
}

A module:

@Module
public class GiftListModule {
    private final GiftListView giftListView;

    public GiftListModule(GiftListView giftListView) {
        this.giftListView = giftListView;
    }

    @Provides GiftListView provideGiftListView() {
        return giftListView;
    }

    @Provides GiftListPresenter provideGiftListPresenter(GiftListView giftListView) {
        return new GiftListPresenterImpl(giftListView);
    }
}

B graph:

@FragmentScope
@Component(modules = GiftDetailsModule.class, dependencies = GiftListGraph.class)
public interface GiftDetailsGraph {
    void inject(GiftDetailsFragment giftDetailsFragment);

    GiftDetailsPresenter getGiftDetailsPresenter();

    final class Initializer {
        public static GiftDetailsGraph init(GiftListGraph giftListGraph, GiftDetailsView giftDetailsView) {
            return DaggerGiftDetailsGraph.builder()
                                      .giftDetailsModule(new GiftDetailsModule(giftDetailsView))
                                      .giftListGraph(giftListGraph)
                                      .build();
        }
    }
}

B module:

@Module
public class GiftDetailsModule {
    private final GiftDetailsView giftDetailsView;

    public GiftDetailsModule(GiftDetailsView giftDetailsView) {
        this.giftDetailsView = giftDetailsView;
    }

    @Provides GiftDetailsView provideGiftDetailsView() {
        return giftDetailsView;
    }

    @Provides GiftDetailsPresenter provideGiftDetailsPresenter(GiftDetailsView giftDetailsView,
            GiftListPresenter giftListPresenter) {
        return new GiftDetailsPresenterImpl(giftDetailsView, giftListPresenter);
    }
}

Main App:

public class MainApp extends Application {
    private static MainApp sInstance;
    protected AppGraph appGraph;
    protected GiftListGraph giftListGraph;

    @Override
    public void onCreate() {
        super.onCreate();
        sInstance = this;
        appGraph = AppGraph.Initializer.init(this);
    }

    public static MainApp getInstance() {
        return sInstance;
    }

...

    public GiftListGraph getGiftListGraph(GiftListView view) {
        return giftListGraph = GiftListGraph.Initializer.init(appGraph, view);
    }

    public GiftDetailsGraph getGiftDetailsGraph(GiftDetailsView view) {
        return GiftDetailsGraph.Initializer.init(giftListGraph, view);
    }

... }

Thanks for any help you can give me :)

Upvotes: 1

Views: 796

Answers (1)

bond
bond

Reputation: 11336

From DI perspective you are seeing the correct behavior. When you are calling get list graph or detail graph, you are building entirely new graph. (See. new Module calls in your initializer calls). Hence you are getting new instance each time.

There are few options I would consider.

  1. One: Have a callback interface defined at the activity scope. Have activity implement it. In the process of creating fragment graphs pass the callback impl instance (activity or some impl class) as argument. Your fragment a/b presenter can use that as a dependency. Now both fragment presenter gets a call back.

  2. Two: Use event bus or broadcast receivers that run at app scope or activity scope. Use that to post message back and forth.

Hope this gives you some ideas.

Upvotes: 2

Related Questions