Open ksloginov opened 9 years ago
Ok, I didn't succeed but, probably someone can guide me from this point:
The initial Dagger Registration:
@Module(
injects = {
MainActivity.class,
},
library = true,
complete = false
)
public class DaggerConfig {
@SuppressWarnings("unused")
@Provides @Singleton Gson provideGson() {
return new GsonBuilder().create();
}
}
MainScreen, whose View is hosting ViewPager:
@Layout(R.layout.screen_main) @WithModule(MainScreen.Module.class)
public class MainScreen extends Path {
@dagger.Module(injects = MainView.class, addsTo = DaggerConfig.class)
public static class Module {}
@Singleton
public static class Presenter extends ViewPresenter<MainView> {
@Inject
public Presenter() {}
}
}
MainView:
...........
@Inject
MainScreen.Presenter presenter;
...........
@Override protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.inject(this);
final Path[] screens = {
new SubScreen("1"),
new SubScreen("2"),
new SubScreen("3"),
};
CustomPagerAdapter customPagerAdapter = new CustomPagerAdapter(getContext(), screens );
customPagerAdapter .setAdapter(firstRunPagerAdapter);
}
.....
Now, the main part, SubScreen (3 similar screens, that differs only by the parameters we are passing into them => they should adjust views according these parameters)
@Layout(R.layout.screen_subscreen) @WithModule(SubScreen.Module.class)
public class SubScreen extends Path {
private final String title;
public SubScreen(String titleParam) {
title = titleParam;
}
@dagger.Module(injects = SubView.class, addsTo = DaggerConfig.class)
public class Module {
@Provides
SubViewMetadata provideSubViewMetadata() {
return new SubViewMetadata(backgroundColor, title);
}
}
@Singleton
public static class Presenter extends ViewPresenter<SubView> {
private String title;
@Inject
public Presenter(String title) {
this.title= title;
}
@Override
protected void onLoad(Bundle savedInstanceState) {
super.onLoad(savedInstanceState);
if (!hasView()) {
return;
}
getView().setTitle(subViewMetadata.title);
}
}
}
and it's view
public class SubView extends FrameLayout {
@InjectView(R.id.subViewTitleTextView)
TextView subViewTitleTextView;
@Inject
SubScreen.Presenter presenter;
public SubView(Context context, AttributeSet attrs) {
super(context, attrs);
ObjectGraphService.inject(context, this);
}
public void setTitle(String title) {
subViewTitleTextView.setText(title);
}
@Override protected void onAttachedToWindow() {....}
@Override protected void onDetachedFromWindow() {....}
......
}
Custom Pager adapter:
public class CustomPagerAdapter extends PagerAdapter {
private final Context context;
private final Path[] screens;
public CustomPagerAdapter(Context context, Path[] screens) {
this.context = context;
this.screens = screens;
}
@Override
public int getCount() {
return (screens == null)? 0 : screens.length;
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view.equals(o);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Path screen = screens[position];
MortarScope originalScope = MortarScope.getScope(context);
MortarScope newChildScope = originalScope.buildChild().build("tutorialpage" + (new Random()).nextInt(999999));
Context childContext = newChildScope.createContext(context);
View newChild = Layouts.createView(childContext, screen);
container.addView(newChild);
return newChild;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = ((View) object);
container.removeView(view);
MortarScope.getScope(view.getContext()).destroy();
}
}
The problem statement: it's crashing, as SubView class hasn't been added into list of Injections at the "Layouts.createView(childContext, screen);" moment in the Adapter, and I can't add it by default, because I want to have a @provider of data from SubScreen to SubScreen.Presenter. (I'm using local variable.
If I add SubView.class into list of injections and convert local Screen's variables into static, then I'll have 3 identical pages inside the ViewPager (which is logical, as every next call of the constructor - overrides old static variables).
Any help/ideas?
Thanks
Ok, apparently I did something.
First of all, adding SubView into list of globally injected classes. Then modifying SubScreen class:
@Layout(R.layout.screen_subscreen)
public class SubScreen extends Path {
private static String titleStatic; // Introducing static variable
private final String title;
public SubScreen(String titleParam) {
title = titleParam;
}
public void refreshPresenter() {
titleStatic = title;
}
@Singleton
public static class Presenter extends ViewPresenter<SubView> {
private String title;
@Inject
public Presenter() {
}
@Override
protected void onLoad(Bundle savedInstanceState) {
super.onLoad(savedInstanceState);
if (!hasView()) {
return;
}
getView().setTitle(titleStatic);
}
}
}
and then in Custom adapter do this changes:
public class CustomPagerAdapter extends PagerAdapter {
private final Context context;
private final SubScreen[] screens;
public CustomPagerAdapter(Context context, SubScreen[] screens) {
this.context = context;
this.screens = screens;
}
......
@Override
public Object instantiateItem(ViewGroup container, int position) {
SubScreen screen = screens[position];
MortarScope originalScope = MortarScope.getScope(context);
MortarScope newChildScope = originalScope.buildChild().build("tutorialpage" + position);
Context childContext = newChildScope.createContext(context);
screen.refreshPresenter(); // updating the static var with local one!
View newChild = Layouts.createView(childContext, screen);
container.addView(newChild);
return newChild;
}
....
}
I.e. the idea is to keep the local AND static variables in the Screen, if the same screen is going to be reused. And when we inflate the view it - just setting the right value to the static one (that would be used in the Presenter).
It works, though I'm not sure if it's a right way to do it, so would be very happy, if someone can approve this approach or propose a better solution.
In my opinion, your logic of static variable and refreshPresenter()
looks wrong.
See here for an up to date example of view pager with Mortar and Flow: https://github.com/lukaspili/Mortar-Flow-Dagger2-demo
In particular, look at the following classes: SlidesScreen
, SlidePageScreen
, SlidePagerAdapter
.
And in the future, you should use stack overflow for such topic.
At this gist, you can find above solution but with save state functionality. https://gist.github.com/VladSumtsov/2128e0cc0f7c2131c0f971ee26d36ce5
Hi,
This topic has been discussed a while ago and even nice snippet has been posted (https://gist.github.com/kboyarshinov/d30c354541f95ecaeaac), but since then, the Flow and Mortar have changed and I'm a bit confused.
It used to be something like this:
But now, Layouts is no longer part of Flow and requireChild is no longer part of MortarScope.
Does anyone succeed in adapting it for the latest libs versions?
Thanks a lot(all square libraries are so awesome!) & best wishes!