02 Flutter BBS 优雅的使用bloC项目解偶(不仅仅
2019-01-06 本文已影响46人
LOVE信
用户界面使用bloc解偶
用户页面示例block流程图简而言之,业务逻辑需要:
1.转移到一个或几个BLoC,
2.尽可能从表示层中删除。换句话说,UI组件应该只关心UI本身而不关心业务,
3.依赖Streams 使用输入流(Sink)和输出流(Stream),
4.保持平台独立,
5.保持环境独立。
事实上,BLoC模式最初被设想为允许独立于平台重用相同的代码:Web应用程序,移动应用程序,后端。
- 组件通过Sink向BLoC 发送事件,
- BLoC通过流通知组件,
- 由BLoC实现的业务逻辑不是他们关注的问题。
从这个声明中,我们可以直接看到一个巨大的好处。
业务逻辑与UI的分离:
- 我们可以随时更改业务逻辑,对应用程序的影响最小,
- 我们可能会更改UI而不会对业务逻辑产生任何影响,
- 现在,测试业务逻辑变得更加容易。
通用BlocProvider
import 'package:flutter/material.dart';
abstract class BlocBase {
void dispose();
}
class BlocProvider<T extends BlocBase> extends StatefulWidget {
BlocProvider({
Key key,
@required this.child,
@required this.bloc,
}): super(key: key);
final T bloc;
final Widget child;
@override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context){
final type = _typeOf<BlocProvider<T>>();
BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
return provider.bloc;
}
static Type _typeOf<T>() => T;
}
class _BlocProviderState<T> extends State<BlocProvider<BlocBase>>{
@override
void dispose(){
widget.bloc.dispose();
super.dispose();
}
@override
Widget build(BuildContext context){
return widget.child;
}
}
UserBloc
import 'dart:async';
import 'package:flutter_bbs_client/model/userEntity.dart';
import 'package:flutter_bbs_client/service/api.dart';
import 'package:flutter_bbs_client/widgets/bloc_provider.dart';
class UserBloc extends BlocBase{
UserEntity _userEntity;
StreamController<UserEntity> _userController = StreamController<UserEntity>.broadcast();
Sink<UserEntity> get _inUser => _userController.sink;
Stream<UserEntity> get outUser => _userController.stream;
StreamController<String> _refreshController = StreamController<String>.broadcast();
Sink<String> get refreshUser => _refreshController.sink;
UserBloc(){
getUserInfo().then((userEntity){
_userEntity= userEntity;
_inUser.add(userEntity);
});
_refreshController.stream.listen((name){
getUserInfo().then((userEntity){
_userEntity= userEntity;
_userEntity.attention = _userEntity.attention+1;
_inUser.add(userEntity);
});
});
}
@override
void dispose() {
_userController.close();
_refreshController.close();
}
}
用户模型
class UserEntity {
/// 粉丝
double fan;
/// 积分
double integral;
/// 名称
String name;
/// 关注
double attention;
/// id
double id;
/// 文章
double article;
String imageUrl;
UserEntity({this.fan, this.integral, this.name, this.attention, this.id, this.article, this.imageUrl});
UserEntity.empty(){
this.fan = 0;
this.integral = 0;
this.name = '';
this.attention = 0;
this.id = 0;
this.article = 0;
this.imageUrl = 'images/default_avatar.jpg';
}
UserEntity.fromJson(Map<String, dynamic> json) {
fan = json['fan'];
integral = json['integral'];
name = json['name'];
attention = json['attention'];
id = json['id'];
article = json['article'];
imageUrl = json['imageUrl'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['fan'] = this.fan;
data['integral'] = this.integral;
data['name'] = this.name;
data['attention'] = this.attention;
data['id'] = this.id;
data['article'] = this.article;
data['imageUrl'] = this.imageUrl;
return data;
}
}
个人中心页面
import 'package:flutter/material.dart';
import 'package:flutter_bbs_client/bloc/user_bloc.dart';
import 'package:flutter_bbs_client/pages/person_bloc_page.dart';
import 'package:flutter_bbs_client/widgets/bloc_provider.dart';
import 'package:flutter/cupertino.dart';
/// 个人中心页面
class PersonPage extends StatefulWidget {
@override
PersonPageState createState() => new PersonPageState();
}
class PersonPageState extends State<PersonPage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.white10,
body: BlocProvider<UserBloc>(
child: PersonBlocPage(),
bloc: UserBloc(),
)
);
}
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
void didUpdateWidget(PersonPage oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
}
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
}
}
个人中心 PersonBlocPage
import 'package:flutter/material.dart';
import 'package:flutter_bbs_client/bloc/user_bloc.dart';
import 'package:flutter_bbs_client/model/userEntity.dart';
import 'package:flutter_bbs_client/pages/home.dart';
import 'package:flutter_bbs_client/widgets/bloc_provider.dart';
import 'package:flutter_bbs_client/widgets/divider.dart';
import 'package:flutter_bbs_client/widgets/group.dart';
import 'package:flutter_bbs_client/widgets/item.dart';
class PersonBlocPage extends StatefulWidget {
@override
PersonBlocPageState createState() => new PersonBlocPageState();
}
class PersonBlocPageState extends State<PersonBlocPage> {
Future<Null> _refresh(UserBloc userBloc) async {
userBloc.refreshUser.add('refresh');
}
@override
Widget build(BuildContext context) {
final UserBloc userBloc = BlocProvider.of<UserBloc>(context);
return RefreshIndicator(
onRefresh: () =>_refresh(userBloc),
child: StreamBuilder<UserEntity>(
stream: userBloc.outUser,
builder:
(BuildContext context, AsyncSnapshot<UserEntity> snapshot) {
if(!snapshot.hasData) {
return Center(
child: Container(
child: CircularProgressIndicator(),
),
);
}
return ListView(
children: [
_head(snapshot.data),
Center(child: _card(context)),
Center(
child: Padding(
padding: const EdgeInsets.only(left: 15, right: 15.0),
child: SettingsGroup(<Widget>[
SettingsItem(
label: 'FS会员',
iconAssetLabel: 'huiyuan',
type: SettingsItemType.modal,
hasDetails: true,
onPress: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage()),
),
),
SettingsItem(
label: 'FS活动',
iconAssetLabel: 'huodong',
type: SettingsItemType.modal,
hasDetails: true,
),
SettingsItem(
label: '浏览历史',
iconAssetLabel: 'liulanlishi',
type: SettingsItemType.modal,
hasDetails: true,
),
SettingsItem(
label: '我的钱包',
iconAssetLabel: 'qianbao',
type: SettingsItemType.modal,
hasDetails: true,
),
]),
),
)
],
);
}));
}
Widget _card(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0),
child: Card(
color: Colors.white,
elevation: 0.5,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('FS钻石:88'),
],
),
SizedBox(
height: 5.0,
),
CustomDivider(
height: 1.0,
),
SizedBox(
height: 15.0,
),
Row(
children: [
_cardItem('article', '我对文章', '1篇私密', context),
_cardItem('tushu', '我的书架', '含已购', context),
_cardItem('shoucang', '我的收藏', '', context),
_cardItem('jianglibang', '奖励任务', '领FB钻', context),
],
)
],
)),
),
);
}
Widget _cardItem(
String img, String title, String subTitle, BuildContext context) {
return Expanded(
flex: 1,
child: Center(
child: Column(
children: [
Image.asset(
'images/$img.png',
width: 35.0,
),
SizedBox(
height: 5.0,
),
Text(
'$title',
style: TextStyle(fontSize: 15.0),
),
SizedBox(
height: 3.0,
),
Text(
'$subTitle',
style: TextStyle(fontSize: 10.0),
)
],
),
),
);
}
Widget _head(UserEntity uerEntity) {
return Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: Container(
width: 60,
height: 60,
child: CircleAvatar(
backgroundImage: ExactAssetImage('${uerEntity.imageUrl}'),
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'${uerEntity.name}',
style: TextStyle(fontSize: 20.0),
),
Row(
children: [
_headFooter(uerEntity.attention, '关注'),
SizedBox(
width: 30.0,
),
_headFooter(uerEntity.fan, '粉丝'),
SizedBox(
width: 30.0,
),
_headFooter(uerEntity.integral, '积分'),
],
)
],
)
],
),
);
}
Widget _headFooter(num, title) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('$num'),
Text('$title'),
],
);
}
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
void didUpdateWidget(PersonBlocPage oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
}
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
}
}
以上代码可供参考 从项目中提取 并不全 希望可以帮到各位道友,你也可以加入qq群向我提问,若帮到你希望你能给予支持或评论 我尽快回复你的问题
加入QQ群950676175 FlutterBBS群二维码.png