Bloc分包

Bloc的代码书写规范

Bloc的分包

我们之前有一张图片,如下所示:


image

我们可以看到:UI将事件给Bloc,Bloc将事件转为状态还给UI。这个工程以及完成了分离:业务层和UI层。但是呢还有一个问题:数据在哪里?如果按照上图的话,数据应该在Bloc这一层,那么就出现了一个问题:业务逻辑和数据糅合到了一起,我们理想状态应该是:数据和业务逻辑也尽可能分开。如下图所示:


image

在Bloc的模式下我们的应用可以被分为三个部分:数据 层、业务逻辑层、UI层。下面我们看一下 具体应该怎么写每一层。

数据层

数据层:从一个或多个数据源取和操作数据。数据源有:数据库、网络、文件等。数据层虽然是应用的最底层,但是也可以分为两部分:数据的获取和数据的包装。

数据获取

数据获取是为了渠道最为原始的数据,比如从网络get数据,数据库的增删改查,文件的读写等等。表现在代码上就是 某一个具体的方法。

class DataProvider {
    Future readData() async {
        // Read from DB or make network request etc...
    }
}

数据包装

数据包装是为了将一个数据或多个数据 糅合到一起,直接和Bloc进行交互,并且将原始数据进行处理后再交给 Bloc。体现在代码上:

class Repository {
    final DataProviderA dataProviderA;
    final DataProviderB dataProviderB;

    Future getAllDataThatMeetsRequirements() async {
        final RawDataA dataSetA = await dataProviderA.readData();
        final RawDataB dataSetB = await dataProviderB.readData();

        //通过两个数据 拿到业务层需要的数据
        final Data filteredData = _filterData(dataSetA, dataSetB);
        return filteredData;
    }
}

Bloc---业务逻辑层

Bloc接受来自用户的 事件,根据事件去和上述的数据层交互,在根据交互的结果 生成对应的状态交给UI层。一个Bloc可能会依赖多个数据包装类。体现在代码上:

class BusinessLogicComponent extends Bloc {
    //数据包装
    final Repository repository;
    
    //事件转为状态
    Stream mapEventToState(event) async* {
        if (event is AppStarted) {
            try {
                //和数据层交互
                final data = await repository.getAllDataThatMeetsRequirements();
                yield Success(data);
            } catch (error) {
                yield Failure(error);
            }
        }
    }
}

我们知道一个Bloc可能会依赖别他的Bloc,那怎么做到这一点呢?可以通过构造方法传参,也可以通过依赖注入。比如:

class MyBloc extends Bloc {
  final OtherBloc otherBloc;
  StreamSubscription otherBlocSubscription;

  MyBloc(this.otherBloc) {
    otherBlocSubscription = otherBloc.listen((state) {
    });
  }

  @override
  Future close() {
    otherBlocSubscription.cancel();
    return super.close();
  }
}

UI层--表现层

表现层其实就是渲染和用户交互,知道在什么样的状态下渲染出什么样的自己,知道将用户的交互事件传递给Bloc就可以了。比如:

class PresentationComponent {
    final Bloc bloc;

    PresentationComponent() {
        bloc.add(AppStarted());
    }

    build() {
     
    }
}

总结

以上就是Bloc应用的理想分层,这样看来Bloc是一个中转站:接受事件,分发事件,事件map状态。

Bloc命名

事件命名

事件最好命名为过去式,因为从Bloc的角度看,事件已经发生了。

比较常用的方式:Bloc对象+名次+动词(事件)

比如:

CounterStarted ------计数器开始了
CounterIncremented -------计数器增加了

CounterDecremented -------计数器减少了

状态命名

状态最好命名为名词,因为一个状态就是在某一时刻的一个应用快照。

比较常用的方式:Bloc对象+动词+状态,并且一般情况下状态为:Initial | Success | Failure | InProgress

比如:

CounterInitial -----计数器初始

CounterLoadInProgress -----计数器加载中

CounterLoadSuccess ------计数器加载成功

CounterLoadFailure ------计数器加载失败

你可能感兴趣的:(Bloc分包)