Experience in using PureMVC

Posted by jlive on Thu, 17 Feb 2022 10:11:08 +0100

I learned PureMVC a long time ago. This is used by my colleagues in the projects of their former company and current company Revised PureMVC framework

Here are some notes on using it

Initialization order

The more basic the module is, the better it will be initialized before

The initialization order in StartUpCommand is very important
for instance,

public class StartupCommand : SimpleCommand
{
    public override void Execute(INotification notification)
    {
        base.Execute(notification);
        
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.LOAD_EXHIBITION_HALL_DATA);
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.INIT_MINIMAP);
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.DOUBLE_SCREEN_SHOW);
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.INIT_ROAMING_CAMERA);

    }
}

Init here_ The mediator module initialized by minimap will call init almost immediately after initialization_ ROAMING_ Some instructions of the mediator module of camera,

case NotificationNames.UPDATE_ROAMING_CAMERA_LOACL_POS:
                UpdateCameraLocalPosition updateCameraLocalPosition = (UpdateCameraLocalPosition)body;

                GetView().UpdateCameraLocalPosition(updateCameraLocalPosition);
                break;  
            

This instruction will lead to the need for GetView()
However, if the registration is carried out in the same order as at the beginning, when calling GetView(), because init_ ROAMING_ The module corresponding to camera has not been initialized, so if it returns empty, this error will be reported. This error is not easy to be found. So right

public class StartupCommand : SimpleCommand
{
    public override void Execute(INotification notification)
    {
        base.Execute(notification);
        
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.INIT_ROAMING_CAMERA);
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.LOAD_EXHIBITION_HALL_DATA);
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.INIT_MINIMAP);
        ApplicationFacade.GetInstance().SendNotification(NotificationNames.DOUBLE_SCREEN_SHOW);
        
    }
}

Other precautions

  1. The communication between the UI in the module and the Mediator uses BroadCast. The communication between the Mediator and the UI is by reference, as shown below
    UI
public void OnDemoModeToggleChanged(bool isOn)
{
    Broadcast(ON_PLAYMODE_TOGGLE_CHANGED, isOn);
}

Mediator

GetView().AddListener<bool>(PlayerSettingsUI.ON_PLAYMODE_TOGGLE_CHANGED, OnDemoModeToggleChanged);

 private void OnDemoModeToggleChanged(bool switchValue)
    {
        playerSettingsProxy.SetDemoModeEnable(switchValue);
    }
  1. Use of communication between modules GetInstance(). SendNotification(NotificationNames.DOUBLE_SCREEN_SHOW); Way of

  2. The UI is responsible for holding references in the scene, and holding objects in the scene that only belong to its own functions by dragging and dropping references

  3. Mediator s can hold their related proxies or multiple proxies

  4. In StartUpCommand, the Init method of proxy is executed by sending instructions.

  5. Mediator looks for UI objects through tag. A module has a mediator, a UI and a tag

  6. The proxy only sends messages prepared with relevant data. The Mediator of the data in the corresponding proxy needs to register and listen to the relevant messages. If the proxy initializes the relevant data and sends messages to the relevant Mediator, the calling relationship will be disordered.

  7. Generally, mediators need data to be used normally. The method is to initialize after all required data are loaded, because considering that complex mediators may need multiple data, sometimes these data may be loaded slowly, and users may have done more related operations during the loading period. The normal logic is that the related operations are temporarily cached, Wait until the data is loaded back, but think about it carefully. When there are many such actions, the logic of the module will become very complex, so simply do not initialize before all the data is returned, and float the word when clicking. Wait a minute.

  8. Although there is no limit to the number of tags, it is required that the object must be active through tag search, but some UI will be hidden for convenience when editing the UI, so three schemes were thought of at that time
    1. Set an active command to execute all UI s at the beginning, and then close each mediator as needed
    The disadvantage is that all functions are turned on at once, and each function needs additional code to close the relevant sub UI under it. Some complex UIs write a little more code, and after the structure is changed, the code may also need to be re debugged
    The advantage is that if the code part is done well, you can open and close the UI at will at ordinary times, and the UI can work normally
    Hide this part,

    Where is the tag
    The disadvantage is that in multi person development, this approach can not guarantee complete error free. Because you can't accurately close only content every time

  9. The framework process is to load all data first and then load the initialization of all modules, but this is only the sequence of calls. The sequence of execution is not guaranteed by the framework itself. For example, it takes a little time delay for network asynchronous data or disk reading data. Personally, I think it is necessary for the proxy base class to have a flag for loading self initialization data, In addition, each proxy has a message notification of self data initialization and an event notification of the completion of total proxy data initialization. You need to load the module after the total data initialization is completed. Otherwise, the logic may cause each module to monitor the initialization completion of the required data module during initialization, and judge whether the corresponding data module is initialized and obtain data initialization at the beginning of initialization. This is required for some initialization operations that require data. This may be added in the revision framework provided later.

error

  1. The UI part sends a message to Mediator indicating that it is not registered,
    In the first case, there is no registration. In the second case, there is registration, but the function parameters are wrong
        GetView().AddListener<int>(PlayerSettingsUI.ON_MOVE_SPEED_VALUE_CHANGED, OnMoveSpeedValueChanged);

For example, when registering here, the parameter is of integer type, but when actually calling, the parameter is of float type, which will also report an error that there is no listener listening

Topics: Framework