现在要说哪个跨平台开发框架整一个 App 速度快一些,说 Flutter 第二,大概没没有几个敢说第一,Flutter 毫无疑问,是 目前来讲比较火爆的 跨平台研发框架了,Flutter 支持全部的平台,现在已经看到一些小伙伴在使用 Flutter 做 web 开发了,虽然本人不是太推荐,毕竟 web 上还是的 看 React & Vue 系列,这两位大哥目前看来还是更加懂 web 一些,Flutter 因为其自己实现的渲染引擎,因此在多端显示上具备其他跨平台框架不具备的优势,因此注重交互体验一致性的小伙伴来说,这毫无疑问就是首选,今天的主题是基于 Flutter ,如何打造一款快速开发的框架。
基于Flutter定制一套快速的研发框架,我们需要考虑到可维护性、扩展性和性能。以及一些必要的能力,这里就列举一些常用的。
dio
包,因为它提供了更多的功能,如拦截器、全局配置、FormData、请求取消等,基本覆盖了网络请求常见的功能,在拦截器中我们可以实现很多统一处理的业务逻辑,嗯,很棒。ThemeData
来定义不同的主题,结合全局状态广利,可以确保主题切换可以即时反映在应用的UI上。cached_network_image
包来加载和缓存网络图片。它还支持占位符和错误的处理。另外我们也可以考虑一下,如果需要,实现图片预加载和内存管理策略。LayoutBuilder
和FractionallySizedBox
等布局小部件来创建响应式布局,也可以考虑使用flutter_screenutil
等包来简化响应式设计的实现。auto_route
或fluro
等更高级的路由管理包,实现路由拦截器,用于权限验证、日志记录等,让我么专注于业务逻辑的开发,不用将为数不多的精力投放到这里。shared_preferences
、hive
、sqflite
等,设计数据模型和存储API,以便于数据的读取和写入,最好是统一的 Storage 抽象,来屏蔽掉这些持久化的细节。ok,以上就是我们框架的思考,接下来,就需要进入coding 环节了,当然,这里只贴部分思路上来。
1. 网络请求模块
我决定使用dio
库来处理网络请求:
import 'package:dio/dio.dart';
class ApiService {
late Dio _dio;
ApiService() {
_dio = Dio(BaseOptions(
baseUrl: "<https://api.example.com>",// 这里需要做成可配置
connectTimeout: 5000,
receiveTimeout: 3000,
));
initializeInterceptors();
}
Future<Response> getRequest(String endpoint) async {
try {
Response response = await _dio.get(endpoint);
return response;
} on DioError catch (e) {
// Handle DioError here by error type or by error code
throw e;
}
}
void initializeInterceptors() {
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {
// Do something before request is sent
print('Sending request to ${options.uri}');
return handler.next(options); //continue
},
onResponse: (response, handler) {
// Do something with response data
print('Received response');
return handler.next(response); // continue
},
onError: (DioError e, handler) {
// Do something with response error
print('Request error: ${e.message}');
return handler.next(e); //continue
},
));
}
}
2. 主题切换模块
我决定使用使用provider
库来管理主题状态,并允许用户在亮色和暗色主题之间切换,以下是我们 App 入口的架子。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ThemeNotifier with ChangeNotifier {
ThemeData _themeData;
ThemeNotifier(this._themeData);
getTheme() => _themeData;
setTheme(ThemeData themeData) async {
_themeData = themeData;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider<ThemeNotifier>(
create: (_) => ThemeNotifier(darkTheme),
child: MyApp(),
),
);
}
final darkTheme = ThemeData(
primarySwatch: Colors.grey,
primaryColor: Colors.black,
brightness: Brightness.dark,
backgroundColor: const Color(0xFF212121),
accentColor: Colors.white,
accentIconTheme: IconThemeData(color: Colors.black),
dividerColor: Colors.black12,
);
final lightTheme = ThemeData(
primarySwatch: Colors.blue,
primaryColor: Colors.white,
brightness: Brightness.light,
backgroundColor: const Color(0xFFE5E5E5),
accentColor: Colors.black,
accentIconTheme: IconThemeData(color: Colors.white),
dividerColor: Colors.white54,
);
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<ThemeNotifier>(
builder: (context, themeNotifier, child) {
return MaterialApp(
title: 'Flutter Demo',
theme: themeNotifier.getTheme(),
home: Scaffold(
appBar: AppBar(
title: Text('Theme Switcher'),
),
body: Center(
child: Text('Hello World'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
themeNotifier.setTheme(themeNotifier.getTheme() == darkTheme ? lightTheme : darkTheme);
},
child: Icon(Icons.brightness_3),
),
),
);
},
);
}
}
3. 图片加载模块封装
我们使用cached_network_image
库来加载和缓存网络图片。
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
class ImageLoader extends StatelessWidget {
final String imageUrl;
ImageLoader({required this.imageUrl});
@override
Widget build(BuildContext context) {
return CachedNetworkImage(
imageUrl: imageUrl,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
);
}
}
4.布局响应式模块
创建一个简单的响应式布局工具类,这样我们就可以非常方便的做多种布局来适应平板,手机,桌面等。
class ScreenSize {
static bool isSmallScreen(BuildContext context) {
return MediaQuery.of(context).size.width < 600;
}
static bool isLargeScreen(BuildContext context) {
return MediaQuery.of(context).size.width > 1200;
}
static bool isMediumScreen(BuildContext context) {
return MediaQuery.of(context).size.width >= 600 && MediaQuery.of(context).size.width <= 1200;
}
}
5. 数据持久化模块和路由模块
我们使用auto_route
库来自动生成路由表和处理导航,然后使用hive
库来实现本地数据存储。前者是因为可以自动生成路由,后者是性能比较不错。
本篇主要做了一些选型上的考虑,然后将部分的模块进行了封装,下篇将会把整个流程串起来,增加自动化化测试、以及 GitHub Action 上做一个 workflow,方便我们 CI,CD。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。