Excuse me for interrupting you again,I have a problem in usage of controller。
Here is the usage scenario:
first,i add a loadingModel to controller,like this:
` @AutoModel
LoadingEpoxyModel loadingModel;
@Override
protected void buildModels(List<String> data) {
loadingModel.addTo(this);
}`
the view display is a progress full screen.
At the same time,i request data from server,in response to the data from the server,i can do:
My confusion is here,the wiki said :controller not include remove/hide methods about models,so i can not remove/hide loadingModel.i try to use addIf,Unfortunately,i found that it have limits in supporting three case above.
Maybe Typed Controllers can solve this problem.But i have no idea.
I know Epoxy Adapter can solve this problem,but i want to use controller follow you.
dou you have some suggestion?
finally,please forgive me for my bad English if it annoys you.
Happy to help, and no worries about your English, it's good enough :)
If I'm understanding your case, I think you can do something like this:
class DataClass {
boolean isLoading;
boolean error;
List<String> strings = Collections.emptyList(); // empty list by default
}
@Override
protected void buildModels(DataClass data) {
loadingModel.addIf(data.isLoading);
errorModel
.onClick(() -> // callback to retry the request, update the data, and requestModelBuild)
.addIf(data.error);
for (String s : data.strings) {
new DataModel_()
.data(s)
.addTo(this);
}
}
The reason why the controller doesn't support removing models is that every time buildModels is called you start with a completely empty model state and rebuild it from scratch. Ideally you have some sort of Data object representing all of the state and you can decide what models to add to reflect that state.
Epoxy doesn't force you to use a certain data pattern, so you might use an activity/fragment/presenter/whatever, but that presenter should coordinate the network request, update the data state as necessary, and set that data on the controller when it changes so the controller can rebuild models.
Hope that helps! let me know if I can explain it more
@ailuoyi basically, the idea is to get rid of complex state and mutability. Instead of your view being some stateful thing that you tell to change (typical MVP) you can think of the view as some kind of function-like blackbox that takes in a POJO (your UI state) and returns the appropriate user interface. Every time an event happens, you create a new POJO that contains all of your current app state and tell the view layer to render that. In this case, you construct a list of POJOs/EpoxyModels in buildModels and give it to Epoxy, which will render this new state, regardless of which models were in it before.
This idea comes from functional languages and can give you a very unidirectional, predictable data flow without side effects. In a language like Haskell or Elm you can relatively easily construct your whole app as a single function composed of other functions that only transform a single flow of data:
class State(color = BLACK, counter = 0)
// presenter
fun handleEvent(currentState: State, event: Event): State =
when(action) {
COUNTER_CLICK-> currentState.copy(counter = currentState.counter + 1)
COLOR_CLICK -> currentState.copy(color = getRandomColor())
}
// view
fun render(state: State): Ui =
ui {
backgroundColor = state.color
label {
text = counter
}
button {
text = "increase counter"
event = COUNTER_CLICK;
}
button {
text = "change color"
event = COLOR_CLICK;
}
}
then your whole progam is basically:
render(handleEvent(state, event))
@elihart Thank you very much for helping me to solve this problem.With your help,i did some practices.
Now,i have a further understanding of controller.You are right,controller's main responsibilities is to build/rebuild models when data changes. About current state, should be identified by the sort of Data object.Then, add some models to reflect that state accordingly.
So, it has a clear hiberarchy on logic,data flows in one direction,and less error-prone.
That's my current cognition.Please do not hesitate to correct me if I am wrong.
@tschuchortdev I really appreciate you to help me and make me learn a lot.
Gradually I learned the art of controller,and it's very handy to use
Glad it makes sense 👍
Most helpful comment
@ailuoyi basically, the idea is to get rid of complex state and mutability. Instead of your view being some stateful thing that you tell to change (typical MVP) you can think of the view as some kind of function-like blackbox that takes in a POJO (your UI state) and returns the appropriate user interface. Every time an event happens, you create a new POJO that contains all of your current app state and tell the view layer to render that. In this case, you construct a list of POJOs/
EpoxyModels inbuildModelsand give it to Epoxy, which will render this new state, regardless of which models were in it before.This idea comes from functional languages and can give you a very unidirectional, predictable data flow without side effects. In a language like Haskell or Elm you can relatively easily construct your whole app as a single function composed of other functions that only transform a single flow of data:
then your whole progam is basically:
render(handleEvent(state, event))