头图

Author: Light Wine

Currently, Xianyu's main business scenarios are all based on streaming scenarios. There are two types of pages in the main business scenarios of Xianyu: one is complex interactive pages, such as release pages and product details pages; the other is light interaction and requires a certain dynamic ability to meet thousands of people. Operational configuration and fast A/B experiment demand pages, such as homepage, search page, my page, etc.

In these light-interactive, dynamic-operated page scenarios, there are many common processing logics: page layout, data management, event logic-driven data changes, and data-driven view status updates; most of these tasks are often repetitive Work, repetitive code logic.

In terms of R&D efficiency and delivery efficiency, business changes often depend on version releases. The two-week release cycle is often unacceptable for businesses that require rapid launch and response. In order to solve the above problems, under the opportunity of the revision of the homepage of the Flutter version, Xianyu designed a set of page construction architecture design under the streaming scene.

Streaming page container architecture design

In the process of designing the architecture of the flow layout, facing the actual business scenario, the end-to-end flow page container design is solved through the following aspects:

1. On the side of building the platform, realize the ability of page building, component management, protocol arrangement, etc., to connect with the delivery platform, A/B experiment platform and monitoring platform;

2. On the client side, the MVVM model is used to design a common event protocol, abstract common page layout, data management and event processing capabilities, reduce repetitive code development, and improve research and development efficiency. In terms of page layout management, it is deeply integrated with the list container PowerScrollView to achieve efficient page rendering and data-driven page refresh capabilities;

3. Use Alibaba Group DynamicX as a DSL to achieve dynamic template rendering to meet the needs of delivery and operation;

4. In terms of the communication protocol with the server, Xianyu has been practicing the integrated development of Flutter+FaaS in the cloud. With the help of FaaS capabilities, it defines a set of cloud-integrated event protocols to solve the problem of dynamic business logic and reduce releases. Dependence, thereby improving delivery efficiency.

In the design of the streaming page container architecture, the focus includes the following core modules: protocol layer, event center, and data center. The detailed design of these templates is introduced below.

Protocol design

In terms of the design of the page container protocol, after combining Xianyu's business and some technical solutions of Alibaba Group, Xianyu adopted a three-layer protocol design: Page, Section and Component.

  1. The Page layer protocol mainly contains section information of the entire page, as well as configuration information such as pull-down refresh, pull-up load more, etc.;
  2. The section layer protocol includes information about the layout of the current Section, initialization Event, LoadMore Event, and Components;
  3. The Component layer protocol is related to the specific business and is a black box for the container. The specific rendering will be handed over to the business side for processing; the DX analysis rendering Handler is provided by default.

In the design of the communication protocol, all events are transmitted, including: client and server, component and component, page and component, page and App. This is also a cloud-integrated design. In theory, developers only need to consider the sending and receiving of events. Whether the specific event is handled on the client side or on the server side is determined by the corresponding Handler. Under the integrated design of the cloud, event processing is more flexible, and logic can be moved backward more conveniently, and when the business changes, the dependence on release is reduced.

Next, let's take a look at the design of the event center in detail.

The design of the event center

Everything is an event;

In the design of PowerContainer, everything is an event: whether it is data update, message transmission, network request, results returned by the server, or custom local processing logic. Xianyu abstractly defines eight general event types. Through the flow of events, the entire page container completes the rendering and refreshing of the page UI, as well as the expression and execution of business logic.

Take a network request as an example, a pull-down refresh will get the initEvent event of each Section and add it to the event center; the event center finds the corresponding Handler according to the event type to process.

If initEvent configures a remote request, it will be handed over to the remoteHandler to send the network request and transmit the event to the FaaS side; after receiving the Event on the FaaS side, distribute it in the event center of the FaaS side, find the corresponding hsf service and get the data, and finally assemble it into Event is sent to the client; the client continues to let the Event flow in the event center after receiving it.

After processing the event sent by the remote end, EventCenter will send a broadcast of the end of the event, which is convenient for the business to process related custom events.

General event abstraction

Let's take a concrete look at the abstraction of general events:

  1. Restart event: Specify the refresh event of the entire Page or a Section. For the Section that needs to be refreshed, its initEvent event will be added to the event center. The common initEvent is a Remote event, but it can also be any other event.
  2. LoadMore event: The LoadMore event mainly deals with scenarios where more data is loaded in pages.
  3. Update event: The Update event mainly deals with the update of the data source and the refresh of the UI.
  4. Context update event: Each Section has a Context information, which represents the context information requested by the server and the client; the Rmote event request of each Section will send the Context information to the server by default, and the corresponding server can issue it. The Context event updates the Context information of the specified Section; specific usage scenarios such as the page number of paging loading, etc.;
  5. Replace event: Replace event replaces Section information, which will be used in scenes such as tab switching;
  6. Remote event: remote request event;
  7. Native events: local general events, such as page jumps, toast prompts, data burying points, etc.;
  8. Custom event: The business custom event embedded in the version.

Data center design

In the MVVM architecture, the data center assumes the role of ViewModel, handles Update events, and is mainly responsible for data update and UI view refresh. For data Update events, Xianyu abstracts several general data update types according to its own business scenarios: overload, patch, override, and remove. In terms of UI rendering, Xianyu combines the list container PowerScrollView with dynamic template rendering DXFlutter to achieve page rendering and page refresh capabilities after data update.

List container

PowerScrollView is a set of fully functional and high-performance list layout containers implemented by Xianyu, which meets the needs of page containers for waterfall flow, card exposure, anchor positioning and other capabilities. In terms of view rendering and refreshing, PowerScrollView provides a partial refresh capability of the list, which perfectly solves the problem of refreshing the view after the data is updated.

In terms of protocol design, the design of the secondary protocol Section, Footer, and Header corresponds to the design of PowerScrollView one-to-one. The second-level protocol Section defines a unique identification Key, which corresponds to the SectionKey of PowerScrollView in UI rendering. After the data is updated, the page container will implement the partial refresh capability of the view according to the Section Key.

Dynamic template rendering

DXFlutter uses Alibaba Group DinamicX as the DSL, and realizes efficient dynamic template rendering capabilities on the Flutter side. Xianyu uses DXFlutter to implement dynamic template rendering of the Component layer protocol.

In the introduction to the protocol design, it was mentioned that the Component layer protocol is a black box for the page container, so how does the DX card event get through with the page container PowerContainer? How is the black box data updated?

In the DSL, Xianyu customizes the event powerEvent of the page container PowerContainer, through which it can generate the general event type of the page container, and connect the events of the DinamicX card with the page container event center. Take the above code as an example, click the scene of "delete the recommended card in the watch list", you only need to define an update type event in the onTap event, and the subType is remove, you can delete the data and render the UI after the deletion.

However, no identifier is defined here, and there can be multiple identical cards in the list, how do you know which piece of data is to be operated on?

Here, a unique ComponentKey is generated for each Component, and the unique ID of the card is generated according to SectionKey+ComponentKey. In each powerEvent event, the Key is passed to the event center, so that the data model of any Component is located, and the data model is updated according to the event type. At the same time, PowerScrollView can also operate partial refresh of the UI through this Key.

Section state management

In the process of page loading, it is often necessary to display some loading state processing, such as loading animation during loading, retry button in loading failure state, and prompt message that there is no more content state, etc.

In terms of protocol design, each Section defines a state, and the state of the Section is updated when the event center processes Remote request events and response events. By registering the render handler, the loading state Widget is returned for the different states of the Section.

void updateSectionState(String key, PowerSectionState state) {
    final SectionData data = _dataCenter.findSectionByKey(key);
      if (state == PowerSectionState.loading) {
         // 从ViewCenter的config获取loadingWidget
          final Widget loadingWidget = _viewCenter?.config?.loadingWidgetBuilder(this, key, data);
          // ViewCenter调用replace section方法更新UI
          _viewCenter.replaceSectionOfIndex(loadingWidget);
        // 标记需要刷新Section
        data.needRefreshWhenComplete = true;
      } else if (state == PowerSectionState.error) {
          ...
      } else if (state == PowerSectionState.noMore) {
          ...
      } else if (state == PowerSectionState.complete) {
        if (data.needRefreshWhenComplete ?? false) { // 判断是否需要更新Section
              final int index = _dataCenter.fineSectionIndexByKey(key);
              if (index != null) {
                final SectionData sectionData = _dataCenter.containerModel.sections[index];
                final PowerSection section = _viewCenter.initSection(sectionData);
                _viewCenter.replaceSectionOfIndex(index, section);
              }
              data.needRefreshWhenComplete = false;
        }
      }
}

After the section status changes, refresh the UI view through the replaceSection method provided by PowerScrollView.

Tab container support

In the Xianyu homepage scenario, the page container needs to support the layout capability of the Tab container. How does PowerContainer support Tab container support?

Xianyu introduces the concept of Slot in the Section protocol. When building the page, it will specify the Slot Section of the Tab container, and the empty slot that does not display any information by default. Each time the Tab container is switched, the Section information of the page container is modified through the Replace event.

void replaceSections(List<dynamic> sections) {
    if (sections == null || sections.isEmpty || _dataCenter?.containerModel?.sections == null) {
          return;
    }
    for (int i = 0; i < sections.length; i++) {
          SectionData replaceData = sections[i];
          assert(replaceData.slot != null);
          // 寻找Section list中与Slot匹配的index
          int slotIndex = _findSlot(replaceData);
          // 更新dataCenter
          _dataCenter.replaceSectionData(slotIndex, replaceData);
           // SectionData 转换为PowerScrollView所需的PowerSection
           final PowerSection sectionData = _viewCenter?.convertComponentDataToSection(replaceData);
           // 更新viewCenter
           _viewCenter?.replaceSectionOfIndex(slotIndex, sectionData);
           //将替换Section的Restart事件发送到event center
           sendEventRestart(replaceData.key);
    }
}

PowerScrollView also provides the replaceSection method, which is combined with the Section state management mentioned above, which perfectly solves the problem of tab container switching and loading state management.

Summary and outlook

This section mainly introduces how to design and implement a set of streaming page construction from the aspects of page construction, protocol design, end-side container implementation, dynamic template rendering, and cloud-integrated event interaction in light interaction and dynamic operation scenarios. Ability to realize the rapid construction of the page and improve the efficiency of research and development. At the same time, it provides the capability of business dynamics, reduces the reliance on release and improves the delivery efficiency on the line.

Currently, the page container PowerContainer is designed and implemented in the refactoring of the Flutter version of the Xianyu homepage. After using PowerContainer, the repetitive code of the three tab pages on the homepage is greatly reduced, the code logic is unified management, and the man-day workload is reduced by half. In terms of performance, with the optimization of PowerScrollView's partial refresh, Element reuse, frame rendering, differencer, etc., it is better than the original experience in terms of fluency.

There is no silver bullet! The design of such a set of page containers is not intended to be suitable for all business scenarios, but is more suitable for business scenarios that focus on presentation and light interaction and dynamic operations. The cloud-integrated event protocol requires the encapsulation of the event protocol on the server side, which also makes it more suitable for serverless scenarios.

Xianyu will make more attempts to build the platform in the future to truly realize the WYSIWYG fast page building capabilities. In terms of business logic dynamics, it is currently more solved by combining with FaaS and logically moving backwards. However, it is still unable to solve the problem of local custom events relying on the release. In the future, there will be more attempts in this regard to achieve less code or even no code business development.

, 3 mobile technology practices & dry goods for you to think about every week!


阿里巴巴终端技术
336 声望1.3k 粉丝

阿里巴巴移动&终端技术官方账号。