android 部件库
Creating loosely-coupled Reactive Feature Components
创建松耦合的React性特征组件
Re-usability is a pattern that solves the problem of duplication. It can be as simple as creating Functions, Classes, Interfaces to more complex UI-Components and Feature-Components.
可重用性是解决重复问题的一种模式。 它可以像创建功能,类,到更复杂的UI组件和功能组件的接口一样简单。
The article focuses initially on the re-usability of UI-Views(UIComponents) and then the FeatureComponents. Emphasis is on the Dependency-Inversion Principle, where both the Low-level(Feature Component) and High-level component (One incorporating the low-level components) both depend on abstraction, to create loosely-coupled systems.
本文首先关注UI-Views( UIComponents )的可重用性,然后是FeatureComponents的可重用性。 重点在于依赖关系反转原理 ,其中低级(功能组件)和高级组件(一个包含低级组件的组件)都依赖抽象,以创建松耦合的系统。
Before proceeding to Feature Components, we’ll start with a brief overview of UI-Components(re-usability of Views).
在继续进行功能组件之前,我们将首先简要概述UI组件(视图的可重用性)。
UI Component design. Low-level component and High-level Component UI组件设计。 底层组件和高层组件Data is sent downwards from HLC → LLC, while the Events are sent from the LLC → HLC.
数据从HLC→LLC向下发送,而事件从LLC→HLC发送。
Low-Level Component (UIComponent): It only renders itself based on the data provided by the High-level component. And propagates the events to the High-level component(👇). It’s devoid of business-logic.
低级组件(UIComponent):仅根据高级别组件提供的数据进行渲染。 并将事件传播到高级组件(👇)。 它没有业务逻辑。
class UIComponent( private val data: ComponentData, private val eventDispatch: UIComponentEventDispatch) { // Renders based on the data provided by HLC fun render(view: UIComponentView) { view.data = data view.invalidate() } fun onRandomEvent(payLoad: Data) { // Sends the event to the HLC eventDispatch.handleEvent1(payLoad) } } interface UIComponentEventDispatch { fun handleEvent1(payLoad: Data) }High-level Component: Provides the data for the UI-Components(LLC), and handles the events from the UIComponent(👇). Example: Click events. It holds all the business logic. It is a single source of truth that holds the state/data for all the UI-Component.
高级组件 :提供UI组件(LLC)的数据,并处理UIComponent(👇)中的事件。 示例:单击事件。 它包含所有业务逻辑。 它是保存所有UI组件的状态/数据的唯一事实来源。
class HighLevelComponent { // Provides the data for UI component and passes the handler for handling events from UIComponent dispatch val uiComponent = UIComponent(data, UIComponentEventHandler()) // Handles the events from the UIComponent. inner class UIComponentEventHandler: UIComponentEventDispatch { fun handleEvent1(payLoad: Data) { ... } } fun renderPage() { uiComponent.render(uiComponentView) } }UIComponents are useful when there is re-usability of UI-views, while Feature Component has larger functionality.
当UI视图具有可重用性,而Feature Component具有更大的功能时,UIComponent很有用。
Apart from receiving the data, it also produces the data itself. 除了接收数据之外,它还产生数据本身。 Contains its own business-logic. 包含自己的业务逻辑。 Needs lesser hand-holding than UIComponent and is useful for designing SDKs and standalone features. 与UIComponent相比,需要的握持较少,并且对设计SDK和独立功能很有用。Why Reactive Feature Component?:- With multiple Components producing data, we need a way to synchronize them. Ex: Data produced by FC1 might affect FC2.
为什么使用React式特征组件?:-随着多个组件产生数据,我们需要一种同步它们的方法。 例如:FC1产生的数据可能会影响FC2。
We will take a bottom-up approach, where we Design and Implement the Low-level Feature components first, and later look their incorporation into the High-level Component.
我们将采用一种自下而上的方法,在该方法中,我们首先设计和实现低级功能组件,然后再将其合并到高级组件中。
For demonstration purposes, we build a Flight Booking screen. It includes the following four Low-level Feature Components DateSelection, FlightsSelection, HotelSelection, and SummaryComponent.
出于演示目的,我们构建了“航班预订”屏幕。 它包括以下四个低级功能组件DateSelection , FlightsSelection , HotelSelection和SummaryComponent。
Booking screen Wireframe 预订画面线框The design of the FeatureComponent looks like this(👇)
FeatureComponent的设计如下所示(👇)
Design of Feature Components. Also showing the different terminologies. 特征组件的设计。 还显示了不同的术语。Let’s look at the Flight Feature Component
让我们看一下飞行功能组件
Dispatches the events to High-level-Component. This is like a channel through which events are sent to the outside world(HLC).
将事件调度到高级组件。 这就像将事件发送到外界(HLC)的渠道。
interface EventDispatcher /** * Dispatches the events from the FlightFeatureComponent. This is like a channel through which we sent events to the outside world * There are two types of event * 1. Change in FeatureState needs to be propagated * 2. Other events like Clicks that are controlled by the parent and not handled by the current FeatureComponent */ interface FlightEventDispatcher : EventDispatcher { fun onFlightSelection(flight: Flight) }onFlightSelection a flight selection event is sent to the outside world. This may then be used by another FeatureComponent.
onFlightSelection航班选择事件发送到外界。 然后,另一个FeatureComponent可以使用它。
Feature Component receives the events from the High-level component.
功能组件从高级组件接收事件。
interface EventReceiver interface FlightEventReceiver : EventReceiver { // Change in date will let the FlightComponent to update itself. // Makes an API call to fetch the flights for the specified date fun dateChange(date: Date) fun onRemoveSelection() }This is a gateway through which it receives events from the HLC.
这是一个网关,通过它从HLC接收事件。
dateChangeA change in date from another component is received. On reception, it fetches the flights for the said date.
dateChange收到另一个组件的日期更改。 在接收时,它将获取所述日期的航班。
onRemoveSelection clears the selected flight.
onRemoveSelection清除选定的航班。
The Feature Component has its own UI.
功能组件具有自己的UI。
interface UI<V : ViewGroup> { fun render(view: V) } interface FeatureComponent<V:ViewGroup>: UI<V> Every FeatureComponent extends the UI interface, implying that they define their own UI. 每个FeatureComponent都扩展了UI界面,这意味着它们定义了自己的UI。HLC attaches it. render is a public API for the HLC to render the FeatureComponent by passing the view(More detail later in Implementation 👇).
HLC将其附加。 render是HLC通过传递视图来渲染FeatureComponent的公共API(稍后在实现Implementation中进行详细介绍)。
1. EventDispatcher
1. EventDispatcher
class FlightFeatureComponent( override val eventDispatcher: FlightEventDispatcher ) : FeatureComponent<FlightView, FlightEventDispatcher> { fun onFlightSelected(flight: Flight) { eventDispatcher.onFlightSelection(flight) } }EventDispatcher is a dependency of the Feature Component.
EventDispatcher是功能组件的依赖项。
The component passes on the events to this interface. In this case, it sends the selectedFlight event.
组件将事件传递到此接口。 在这种情况下,它将发送selectedFlight事件。
Flight FeatureComponent implements the FlightEventReceiver interface. This provides it the capability to receive events from the HLC.
Flight FeatureComponent实现了FlightEventReceiver接口。 这使它能够从HLC接收事件。
In this case, it receives dateChange and removeSelection events and passes them to its business layer(store).
在这种情况下,它接收dateChange和removeSelection事件,并将它们传递到其业务层( store )。
Flight FeatureComponent implements the UI interface on FlightView defining its own UI.
Flight FeatureComponent在FlightView上实现了UI界面,定义了自己的UI。
Additionally, FeatureComponent additionally coordinates between its own business-layer and the view layer, by acting as a middle-man. (👇)
此外,FeatureComponent还通过充当中间人在其自己的业务层和视图层之间进行协调。 (👇)
Interaction between Business-layer and View-layer of the Feature Component 功能组件的业务层和视图层之间的交互Divide it into 2 parts — Business layer and View-Layer
将其分为两部分-业务层和视图层
To receive events from the FeatureComponents(LLC), HLC implements the dispatcher (FlightEventDispatcher) in the form of inner class (FlightEventDispatchListener), which is then passed on as a dependency for component creation(👆).
从 FeatureComponents(LLC),HLC 接收事件 以内部类( FlightEventDispatchListener )的形式实现调度程序( FlightEventDispatcher ),然后将其作为组件创建(👆)的依赖项传递。
class FlightFeatureComponent(): FlightEventReceiver class BookingScreenViewModel { ... val flightComponent = FlightFeatureComponent(eventDispatcher = FlightEventDispatchListener()) // An event to clear all the selections in the screen fun clearSelections() { flightComponent.onRemoveSelection() } ... }To send events to Feature Component, HLC can directly call the methods of FlightComponent, as it has the capability to receive events. See clearSelections .
要将事件发送到功能部件,HLC可以接收事件,因此可以直接调用FlightComponent的方法。 参见clearSelections 。
What if HLC components have a large number of components? The HLC would be over-burdened with synchronizing and passing the events between different FeatureComponents.
如果HLC组件包含大量组件怎么办? 通过在不同FeatureComponents之间同步和传递事件,HLC将负担沉重。
A better approach would be to make the HLC a mediator for passing events to FeatureComponents.
更好的方法是使HLC成为将事件传递给FeatureComponents的中介者。
Whenever it receives an event from one FeatureComponent, it passes the event blindly to other FeatureComponents. 每当它从一个FeatureComponent接收到事件时,就会将该事件盲目传递给其他FeatureComponents。 All FeatureComponent receive all the events but chooses the events on which they want to react and ignore the rest. 所有FeatureComponent都接收所有事件,但选择它们要对其作出React的事件,而忽略其余事件。 This way both are loosely coupled and any component can be attached to the HLC. 这样,两者都可以松散耦合,并且任何组件都可以连接到HLC。You can find the demonstration example here.
您可以在此处找到演示示例。
翻译自: https://proandroiddev.com/feature-components-in-android-6c193a65d73f
android 部件库