Flutter-总结笔记1

flutter-lottie等

Posted by MetaNetworks on December 5, 2019
本页面总访问量

使用Flutter Core版本:Flutter 1.9.1+hotfix.6 • channel stable

示例:https://github.com/MetaNetworks/FlutterSmsSyncWorker

Flutter-Lottie 动画框架

Flutter APP使用androidx框架,受androidx 原因的影响

截止到2019.12.05,安卓端需要进入flutter-lottie目录(是依赖的目录)将build.gradle中的lottie-android版本由2.7.0改成3.0.2,IOS需要在runner中的info.plist添加一个表项,具体百度~

Example:

注意:LottieView需要有外围的大小限制(放入Container、SizedBox等),否则会页面溢出

1
2
3
4
5
6
7
8
9
10
Container(
  height: 150,
  width: 150,
  child: LottieView.fromFile(
    filePath: 'animation/send.json',
    onViewCreated: (LottieController controller) {},
    autoPlay: true,
    loop: true,
  ),
),

有待摸索:LottieView的controller

Fluro 企业级路由

  • Routes类,进行router的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Routes {
  static String index = "/index";
  static String welcome = "/";
  static String login = "/login";
  static String main = "/main";
  static String smsSend = "/sms/send";
  static String smsGet = "/sms/get";
  static String logout = "/index/logout";

  static void configureRoute(Router router) {
    router.define(index,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return IndexPage();
        }), transitionType: TransitionType.fadeIn);
    router.define(login,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return LoginPage();
        }), transitionType: TransitionType.fadeIn);
    router.define(welcome,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return WelcomePage();
        }), transitionType: TransitionType.fadeIn);
    router.define(main,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return MyHomePage(title: "SMS助手",);
        }), transitionType: TransitionType.fadeIn);

    router.define(smsSend,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return SmsSendPage();
        }), transitionType: TransitionType.fadeIn);
    router.define(smsGet,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return SmsGetPage();
        }), transitionType: TransitionType.fadeIn);

    router.define(logout,
        handler: Handler(handlerFunc: (BuildContext context,Map<String,List<String>> params) {
          return LogoutPage();
        }), transitionType: TransitionType.fadeIn);

  }
}
  • 将fluro与App进行绑定

    使用 generator 绑定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      class MyApp extends StatelessWidget {
        // This widget is the root of your application.
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: '这是一个App',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            onGenerateRoute: router.generator,
          );
        }
      }
    

FutureBuilder

适用于异步显示页面,可以做出先出加载动画,后出数据的动作

future属性里面是异步方法,根据snapshot.connectionState(异步方法的执行情况如还没开始,还在等待,正在执行,执行完成)的不同可以显示不同画面

注意:点击会改变页面局部的控件如Textfield等不要放在FutureBuilder中,以Textfield为例,否则点击Textfield后会APP重新调用future中的方法,导致页面重载无法输入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class _IndexPageState extends State<IndexPage> {
  bool isLogin;

  Future<void> _init() async {
    Application.sp = await SharedPreferences.getInstance();
    isLogin = await SmsTool.checkIfLogin();
    if (isLogin) {
      Navigator.popAndPushNamed(context, Routes.main);
    } else {
      Navigator.popAndPushNamed(context, Routes.login);
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _init(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
            // TODO: Handle this case.
            break;
          case ConnectionState.waiting:
            // TODO: Handle this case.
            break;
          case ConnectionState.active:
            // TODO: Handle this case.
            break;
          case ConnectionState.done:
            // TODO: Handle this case.
            break;
        }
        return Center(
          child: Container(
            width: 200,
            height: 200,
            child: LottieView.fromFile(
              filePath: 'animation/loading/loading_1.json',
              autoPlay: true,
              loop: true,
              onViewCreated: (LottieController controller) {},
            ),
          ),
        );
      },
    );
  }
}

Dio 网络框架

网上好多都和我的Flutter不一样!他们的教程太老了!

  • 请求示例代码

    dio.post指post方法,除此之外还有get、put等

    Options里可以定义contentType,cookie等

    data里可以定义请求body

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
      static Future<void> login(String phoneNumber, String password) async {
          try{
            Response response = await Application.dio
                .post(Config.loginUrl, options: Options(contentType: ContentType.json),
                 data:{'username' : phoneNumber,'password':password}
            );
            print(response.data);
            Fluttertoast.showToast(msg: "Login Success");
            SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
            sharedPreferences.setString('uid',response.data['uid']);
            sharedPreferences.setString('id',response.data['id']);
            sharedPreferences.setString('username',phoneNumber);
            sharedPreferences.setString('password',password);
          }
          on DioError catch(e){
            String message = e.response.data["message"];
            Fluttertoast.showToast(msg: message != null?message:"网络异常");
          }
        }
    

布局一些建议

  • 多用Expand、Flexible等会根据屏幕大小适配的控件