使用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
等会根据屏幕大小适配的控件