fpuremvc 1.0.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 46

Build Status Coverage Status PRs Welcome pub package best-flutter

puremvc #

puremvc for flutter

页面与逻辑完全分离,页面可以不知道模型,模型可以不知道页面。

为什么要有这个库?

目前的状态管理库要么使用过于复杂,要么并不能做到模型和页面完全隔离,所以有这个库。

Getting Started #

导入

import 'package:fpuremvc/fpuremvc.dart';

因为这里puremvc已经被占用了,所以只能这样

流程

定义一个模型,模型用于存储数据和接收dispatch的消息并处理,完成之后notify通知已经完成


class NumberModel extends BaseModel {
  @override
  String get name => "number";

  int counter = 0;

  @override
  Future setup() async {
    await Future.delayed(new Duration(seconds: 2));
  }

  @override
  update(String event, data) {
    if (event == "add") {
      return add();
    }
  }

  int add() {
    ++counter;
    return counter;
  }
}


创建模型,一般保存为App的实例



NumberModel numberModel = new NumberModel();

页面使用:

第一种:StatefulWidget

import 'package:flutter/material.dart';
import 'package:fpuremvc/fpuremvc.dart';



class StatefulDemo extends StatefulWidget {
  final int counter;

  StatefulDemo({Key key, this.counter}) : super(key: key);

  @override
  _StatefulDemoState createState() => _StatefulDemoState();
}

class _StatefulDemoState extends ObserverState<StatefulDemo> {
  int _counter;

  @override
  void initState() {
    _counter = widget.counter;
    bind("number/add@ok", onCounter);
    bind("number/asyncAdd@ok", onCounter);
    /// the the lines can be replaced by  bind("number/*@ok", onCounter); or just bind("number/*", onCounter)


    super.initState();
  }

  void onCounter(int counter) {
    this._counter = counter;
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatefulDemo"),
      ),
      body: Column(
          children: <Widget>[
            Text(
              'Model is setting up,so if you click button quickly,it looks like not working',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            new RaisedButton(
              onPressed: () {
                Navigator.pushNamed(context, "stateless");
              },
              child: new Text("Stateless"),
            ),


            new RaisedButton(
              onPressed: ()=>dispatch("number/add"),
              child: new Text("Sync increment"),
            ),

            new RaisedButton(
              onPressed: ()=>dispatch("number/asyncAdd"),
              child: new Text("Async increment"),
            ),


          ],
        ),


    );
  }
}

第二种:通过build来创建StateLess页面

import 'package:flutter/material.dart';
import 'package:fpuremvc/fpuremvc.dart';

@immutable
class StatelessDemo extends StatelessWidget {
  final int counter;

  StatelessDemo({this.counter});

  void _incrementCounter() {
    dispatch("number/add");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatelessDemo"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.display1,
            ),
            new RaisedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: new Text("Back"),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}


使用一些路由组件使得页面和模型隔离,或者全局保存这些WidgetBuilder

WidgetBuilder statelessBuilder= PureMvc.eventBuilder(["counter"], (c){
    return StatelessDemo(title: 'Flutter Demo Home Page',counter: numberModel.counter,);
});
Navigator.push(context, new MaterialPageRoute(builder: statelessBuilder));

直接使用routers



Map<String, WidgetBuilder> routers = {

  /// 定义个WidgetBuild,在监听到通知number/*@ok的时候重建, * 为通配符
  "stateless": PureMvc.eventBuilder(["number/*@ok"], (c) {
    return StatelessDemo(
      counter: numberModel.counter,
    );
  }),

    .....
  "stateful": (c) {
    return StatefulDemo(
      counter: numberModel.counter,
    );
  }
};


Navigator.pushNamed(context, "stateful")

异步 #


class NumberModel extends BaseModel {
  @override
  String get name => "number";

  int counter = 0;

  @override
  Future setup() async {
    await Future.delayed(new Duration(seconds: 2));
  }

  @override
  update(String event, data) {
    if (event == "add") {
      return add();
    } else if (event == 'asyncAdd') {
      return asynAdd();
    }
  }

  int add() {
    ++counter;
    return counter;
  }

  asynAdd() async {
    await Future.delayed(new Duration(milliseconds: 500));
    ++counter;
    return counter;
  }
}
`

模型中的asynAdd方法为异步方法,此时可以使用 dispatch('number/asynAdd') 调用,

注意这里的判断

else if (event == 'asyncAdd') {
      return asynAdd();
    }
  • 当异步方法返回成功时候,将会通知事件 number/asynAdd@ok
  • 当异步方法返回失败时候,将会通知事件 number/asynAdd@fail
  • 当异步方法结束时候,将会通知事件 number/asynAdd@end

[1.0.0] #

  • 完善测试

[0.3.0] #

  • 完善测试

[0.2.1] #

  • bind绑定的方法返回false可不刷新widget

[0.2.0] #

  • 完善setup 过程中的异常处理

[0.1.9] #

  • setup 过程中的异常处理

[0.1.8] #

  • Fix requestModel

[0.1.7] #

  • EventListener参数改成named

[0.1.6] #

  • 修正EventListener

[0.1.5] #

  • 增加EventListener组件

[0.1.4] #

  • 模型不一起初始化

[0.1.3] #

  • 打印的日志展示模型、事件

[0.1.2] #

  • PureMvc增加requestModel方法,在获取的时候判断模型有没有初始化完毕,如果没有则等待

[0.1.1] #

  • 支持通配符监听事件

[0.1.0] #

  • setGlobalErrorHandler 改成static

[0.0.9] #

  • update返回非future数据,也可以有默认通知

[0.0.8] #

  • updte中的异常可以通过 Puremv.setGlobalErrorHandler 来处理,如果未设置,则打印异常

[0.0.7] #

  • 在notify的时候检查调用异常,调整函数参数个数

[0.0.6] #

  • 监控update返回值,如果是Future,则通知 model/event@ok 或者 model/event@fail事件
  • 在update之前发送 model/event@start事件
  • 在update之后发送 model/event@end事件

[0.0.5] #

  • 修复setup不返回值后出现异常的bug

[0.0.4] #

  • setup重复的bug
  • 等待setup完成之后发送事件

[0.0.3] #

  • dispatch 后面一个参数可选

[0.0.1] - init version #

  • 基本使用

example/lib/main.dart

import 'package:example/pages/home.dart';
import 'package:example/routers.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
      routes: routers,
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  fpuremvc: ^1.0.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:fpuremvc/fpuremvc.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
80
Overall:
Weighted score of the above. [more]
46
Learn more about scoring.

We analyzed this package on Jul 3, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

because of import path [fpuremvc] that is in a package requiring null.

Health suggestions

Fix lib/_src/_listener_info.dart. (-0.50 points)

Analysis of lib/_src/_listener_info.dart reported 1 hint:

line 73 col 14: The member 'setState' can only be used within instance members of subclasses of 'package:flutter/src/widgets/framework.dart'.

Format lib/_src/_pure_mvc.dart.

Run flutter format to format lib/_src/_pure_mvc.dart.

Format lib/fpuremvc.dart.

Run flutter format to format lib/fpuremvc.dart.

Maintenance suggestions

The package description is too short. (-20 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
Dev dependencies
flutter_test