Flutter 研发阶段性总结(二) 基本需求研发总结

由于不是专门做App研发的,可能思维比较狭隘,以下两点估计能覆盖大部分的需求场景:

  1. 基于HTTP网络请求的增删改查
  2. 基于本地数据库,比如sqlite的增删改查

。。。。。。别打我,也可能就我自己这么认为。

所有开发的基础 - Future

这个应该前端的同学很熟悉,从以前的事件监听,promise到现在的Future都是异步开发的思想。说白了就是:

我封装了一个任务和参数交给系统,你把这个事情做了,成功后做啥,失败后做啥。在任务执行期间我就可以做别的事情了。

异步在Flutter中,或者说是在Dart的底层机制中是无所不在的,因此它是所有功能研发的基础。

void main () {
  Future(() {
    print('future craeted');
    return 12;
  }).then((data) {
    print('received data $data');
  });
  print('main func done');
}

这里输出的顺序应该是:

  1. main func done
  2. future created
  3. received data 12

因为,Future((){}).then((){}); 仅做了封装了一个任务并交给Dart,随后立马运行到 print('main func done'); 这行,因此main func done 是最先输出的。

其次是异步代码的编排,如果仅仅依靠Future的then和catchError, 实现异步的调度,一旦需要多个异步操作先后依赖则很容易出现如下代码:

futurefunc1().then((data1){
  futurefunc2(data1).then((data2){
    futurefunc3(data2).then((){}).catchError((error){});......
  }).catchError((error){
    print('futuer 2 error');
  });
}).catchError((error){
  print('future 1 error');
});

代码是很难读懂的,此时async出现了

futurefunc1() async {}
futurefunc2(data1) async {}
futurefunc3(data2) async {}
main() async {
  var data1 = await futurefunc1();
  var data2 = await futurefunc2(data1);
  var data3 = await futurefunc3(data2);
}

这样异步任务的依赖关系就很明白了。
在此基础上,http,sqlite等相关工具调用函数返回Future就很容易理解了。

Future与Widget

1) 用状态控制界面

这个是最直接的思路,通过界面Widget绑定变量,在state改变时候重新绘制就行

class BasePage extends StatefulWidget {
  @override
  _BasePageState createState() =>_BasePageState();
}

class _BasePageState extends State<BasePage> {
  // 变量
  bool _loading = false;
  String _result = '';
  
  @override
  initState() {
    super.initState();
    loadData();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      // 载入过程中显示载入中,结束后显示获得的结果
      child: _loading? Text('载入中'): Text(_result);
    );
  }

  /// 页面逻辑
  loadData() {
    setState((){
      _loading = true;
    });
    
    getData().then((data){
      setData((){
        _loading = false;
        _result = data;
      });
    }).catchError((error){
      print('error $error');
      setData((){
        _loading = false;
        _result = 'Oops';
      });
    });
  }
  
  /// 某种耗时的获取数据的方法比如http或者sql
  Future<String> getData() async {
    return 'takes time to get some thing';
  }
}

2) FutureBuilder

1)方法仍然需要用户手动维护载入状态,执行中啥样,成功啥样,错误啥样,都需要自己setState来操作,比较麻烦。
Flutter官方提供了基于Future的Widget构造方法,用户仅需要提供Future的来源,各种状态的显示样式即可,整个loadData页面逻辑函数就可以去掉了。上述同样的功能即变为 :

class BasePage extends StatefulWidget {
  @override
  _BasePageState createState() =>_BasePageState();
}

class _BasePageState extends State<BasePage> {
  // 变量
  bool _loading = false;
  String _result = '';
  
  @override
  Widget build(BuildContext context) {
    /// 这里是FutureBuilder 因为Future提供函数getData()返回的是Future
    /// 其实可以不指定String类型, 即FutureBuilder(), 这样默认是dynamic类型
    return FutureBuilder<String>(
      future: getData,
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return Text('Oops');
        } else if(snapshot.hasData){
          return Text(snapshot.data);
        } else {
          return Text('载入中');
        }
      }
    );
  }
   
  /// 某种耗时的获取数据的方法比如http或者sql
  Future<String> getData() async {
    return 'takes time to get some thing';
  }
}

3) 其它

如果界面的值不是一次发生变化,而是在一个时期内会有多次变化,则可以使用StreamBuilder, 这个控件在后期会提到。

基本控件

控件包管理方面,Google提供了pub,和Java的Maven, Gradle类似,在Flutter项目的yaml文件中声明dependency并标明版本即可把控件依赖加入到项目中。 以下提供Http和Sql增删改查的基本工具。

1) HTTP - Dio

这个是Flutter上最为流行的Http工具库,封装了很多基本方法,get、post、文件上传、文件下载等等
项目地址
Dio

Dio dio = Dio();

dio.get('http://www.baidu.com'); // 返回Future
dio.post('http://api.baidu.com', data: {"param":value}); // 返回Future
// ......还有很多很多,请见官方文档

2)Sql - sqflite

这个是Flutter上Sqlite实现工具库,同样也是封装得很完完善的库了。
项目地址
sqflite

Database db = await openDatabase(path,readOnly: false);
db.rawQuery('SELECT * FROM table'); // 返回Future>
// .... 还有很多

结合上边的 Future和FutureBuilder,想必小伙伴们已经知道怎么做了吧。

你可能感兴趣的:(App)