Moxy framework developed by us with Yura is widely used in Android development. It provides the MVP implementation of the pattern when working with Activity, Fragment and View, completely separating the “callback hell” of their life cycle from the presenter.
This behavior is implemented by the ViewState entity, which proxies method calls between Presenter and View, while keeping some of them in the queue based on special strategies. When recreating a View, not all methods are called, but only those that are in the queue at the moment.
In this article, we will describe how the out-of-box strategies work, and when to use each of them. On the mechanism of the work of strategies from the inside and writing custom strategies, see
Part 2 .
Moxy working principles')
The queue of commands (methods that are called on the view) in the presenter define the View states after the re-creation.
The commands in the queue are saved according to the strategy specified for it in the method of the View interface. ViewState itself is generated at compile time based on the View interface and the annotations used in it.
Inaccurate use of strategies can lead to incorrect application behavior and memory overflow.
Commands can be applied to the View only when it is in the
active state — in the interval between calls to the
getMvpDelegate (). OnAttach () and
getMvpDelegate (). OnDetach () methods from
Activity ,
Fragment, or custom
android.view.View .
Circuit deviceTo illustrate how strategies work, we will use the following scheme:

The X axis is the time scale (left-to-right time direction).
Circles indicate teams, identical teams (respectively, having the same strategy) are indicated by circles with the same color and number.
The axis of the presenter displays the commands that the presenter initiates using the
getViewState (). DoSomething (args) method. The team performed by the presenter has the strategy that is considered in this scheme, unless otherwise indicated.
The ViewState axis is the state of a queue of commands that are applied to the View upon its subsequent re-creation. Commands are applied sequentially, from bottom to top. The initial state of the ViewState is displayed in the leftmost position on the axis.
The View axis is a set of commands that have been applied to the View. The orientation change icon means re-creating the View. The View axis can start from the middle of the diagram - this means that the View has moved to the active state from this very moment.
Out of box strategiesMoxy provides the following strategies by default:
AddToEndStrategy - execute the command and add the command to the end of the queue
AddToEndSingleStrategy - execute a command, add it to the end of the queue and delete all its previous instances
SingleStateStrategy - execute the command, clear the queue and add the command to it
SkipStrategy - execute the command
OneExecuteStrategy - execute the command as soon as possible
Let's take a closer look at how they work and when they should be applied.
AddToEndStrategyAddToEndStrategy is the simplest strategy, which is to add a command to the end of the queue:

When calling a team presenter (2) with AddToEndStrategy strategy:
- Command (2) is added to the end of the ViewState queue
- Command (2) applies to View if it is in active state.
When recreating a View:
- Commands from the ViewState queue are sequentially applied to the View.
AddToEndSingleStrategyThis strategy differs from AddToEndStrategy in that there can be only one instance of each command in the ViewState queue marked with this strategy.
Extended useWhen using custom commands, you can change the queue status (for example, duplicate any of the available commands), but this should be done with great care)

When calling a team presenter (2) with the AddToEndSingleStrategy strategy:
- The command (2) is added to the end of the ViewState queue.
- In case the command has already been in the queue (2), the old command is removed from the queue
- Command (2) applies to View if it is in active state.
When recreating a View:
- Commands from the ViewState queue are sequentially applied to the View.
SingleStateStrategyThis strategy is similar in principle to AddToEndSingleStrategy. The difference is that when a command with this strategy is entered into the ViewState, the command queue is cleared completely.

When calling a team presenter (1) with the SingleStateStrategy strategy:
- The command queue is completely cleared.
- The command (1) is added to the end of the ViewState queue.
- Command (1) applies to View if it is active
When recreating a View:
- Commands from the ViewState queue are sequentially applied to the View.
SkipStrategySkip strategy does not change the viewstate stack. The command is applied to the View, only if it is in the active state.

The team behaves differently, depending on the presence of a view in the active state.
a) If the View is in the active state:
When calling a team presenter (4) with the SkipStrategy strategy, if the View is in the active state:
- Command applies to View
- Team queue remains unchanged.
When recreating a View:
- Commands from the ViewState queue are sequentially applied to the View.
b) In the
absence of the View in the active state:
When calling a team presenter (4) with the SkipStrategy strategy, in the
absence of the View in the active state:
- Command does not apply to View
- Team queue remains unchanged.
When recreating a View:
- Commands from the ViewState queue are sequentially applied to the View.
OneExecuteStrategyThis strategy is very similar to SkipStrategy. The difference is that when there is no view in the active state, the command waits until it appears, and then it is applied exactly once.

The team behaves differently, depending on the presence of a view in the active state.
a) If the View is in the active state:
When a team calls a presenter (4) with the OneExecuteStrategy strategy, if the View is active (Behavior is completely the same as SkipStretegy):
- Command applies to View
- Team queue remains unchanged.
When recreating a View:
- Commands from the ViewState queue are sequentially applied to the View.
b) In the
absence of the View in the active state:
When calling a team presenter (4) with the OneExecuteStrategy strategy, in the
absence of the View in the active state:
- Command (4) is added to the end of the ViewState queue
When View is active:
- Commands from the ViewState queue are sequentially applied to the View.
- When command (4) is executed, it is removed from the command queue. At the subsequent re-creation of the View command (4) will not be called.
Lack of strategy for the methodThe absence of an explicit indication of the strategy of the method leads to its automatic output based on the strategy for the entire interface and the default strategy. Currently, the default strategy is AddToEndStrategy.
Command scopeIn this section, we have collected typical cases of the use of commands.
AddToEndStrategy - used when you need to consistently apply several commands that need to be
reapplied when recreating a View.
Example: The organization screen consists of 3 blocks: general information, promotions, purchase history. These parts can be loaded and displayed on the screen asynchronously. After re-creating it is important to display information in all blocks. All methods will be marked with the strategy AddToEndStrategy
AddToEndSingleStrategy - used when the command is to be used when recreating a view no more than once.
Example: There is a loading indicator on the screen, the visibility of which is changed by calling the View method: toggleLoading (visible: Boolean).
Spoiler: here and hereafter code examples are shown on Kotlin.This method will have an AddToEndSingleStrategy strategy.
SingleStrategy - applies if we don’t care about the result of commands that worked before it.
Example: Profile screen data is downloaded from the network. The screen has 3 mutually exclusive states: loading, data display and screen — stub. Accordingly View has methods showLoading (), showData () and showStub (). All three teams will have the strategy SingleStateStrategy.
SkipStrategy - used in case we need to perform some action right now and only in case there is a View in the active state.
Example 1: There is a screen for editing user data. When you click the save button, the load indicator is displayed by calling the toggleLoading command (show = true). If the load fails, the screen returns to its original state with the command toggleLoading (show = false) and the SnackBar is displayed with the error information with the command showLoadingError (). The last team will have a SkipStrategy strategy, since the result of its execution is needed only with the active screen and should not be saved when changing the configuration.
Example 2: Starting an animation after some user action. It makes sense to use the command only once, and in the absence of an active view you do not need to save it to a queue.
OneExecuteStrategy - used if we need to perform some action when the View first appears in the active state.
Example 1: Opens the next screen. Launching a new Activity, Fragment, or FragmentDialog is conveniently performed through this strategy. In this case, we will have guaranteed 1 launch.
RefinementTo be more precise, guaranteed launch at the first Attachment View. If for some reason View was not in the active state and it did not come to the active state, the command will not be invoked. This situation is theoretically possible, you need to keep this in mind.
OneExecuteStrategy and SkipStrategy are very similar, be careful when using them.
How to avoid problems due to strategies?When using strategies, you may encounter two kinds of problems:
Problem 1. Unnecessary teams in the queueWhen using
only AddToEndStrategy, which is the default strategy, the queue is gradually increasing. This may cause:
- Freeze ui when attaching View to Presenter
- Memory overflow
Decision:Try to minimize the size of the command queue by setting strategies.
Problem 2. Wrong state during re-creation viewOften, an application requires only portrait orientation, as a result of which it is fixed during development, however, the re-creation of the view takes place not only when the orientation changes, but also during other configuration changes.
Decision:When developing leave the possibility of changing the orientation of the application. This will help you to control not only the correct application of strategies, but also the other side effects of changing the configuration of the device.
ConclusionMoxy strategies are a fairly flexible tool, the careless use of which can lead to logical errors. We hope this article will make using Moxy more transparent and obvious.
In
Part 2, we consider the mechanism of how strategies work from the inside and how to create custom strategies.
Let your code always execute as you designed it!
from the authors of the Moxy
Xanderblinov and
senneco libraryMaterials on the topic