玩Android Flutter版本,通过项目了解Flutter项目快速搭建开发

继上个月的纯血鸿蒙版的玩Android,这次继续Flutter版本的玩Android实战。整体完成度80%,可自行编译打包使用。不得不说,flutter的生态发展还是挺好的,各种三方开源库、plugin比较完整。这对于项目快速迭代开发还是挺友好的~

仓库地址

wan_android_flutter

项目介绍

项目common模块封装了常用以下的功能,可用于其他项目的快速迭代开发

  1. 支持浅色/深色模式(跟随系统)
  2. 支持语言切换(跟随系统)
  3. 资源文件管理
  4. 支持toast、支持全局loading
  5. 支持页面导航路由
  6. 通用的appbar
  7. 支持沉浸式状态
  8. ...

相关技术

一、iFlutter插件使用

通过AndroidStudio安装iFlutter plugin,可以加速flutter开发。项目中主要用于:

  • 资源文件管理:避免在代码中硬编码图片名字
  1. 在assets目录存放资源
  1. 通过jFlutter生成AssetsRes文件(iflutter可以设置自动监听文件变化)
  1. 使用
arduino 复制代码
Image.asset(
  AssetsRes.HEART,
  width: 25,
  height: 25,
)
  • json转dart:网络请求时特别好用,接口返回数据直接生成相应model
  1. 通过iFlutter生成dart
  1. 输入json,并填写生成dart文件名
二、get_cli

get_cli | Dart package:通过get_cli管理文本

  1. assets/locales下维护各种语言的文本
  1. 通过命令行生成相应的语言文件:locales.g.dart
arduino 复制代码
get generate locales assets/locales
  1. 代码中使用
scss 复制代码
/// 代码使用:通过LocaleKeys.about.tr方式使用
Text(
  LocaleKeys.about.tr,
  style: colorData.textBlack.s18.regular,
)
三、getx

get | Flutter package:更便捷的状态管理与路由管理

  1. 状态管理

flutter的组件少不了状态管理,目前开源的方案比较多,这里采用getx

less 复制代码
/// 需要变更的数据使用obs定义,需要跟随数据变化的widget使用Obx进行包裹即可
class Home extends StatelessWidget {
  var count = 0.obs;
  @override
  Widget build(context) => Scaffold(
      appBar: AppBar(title: Text("counter")),
      body: Center(
        child: Obx(() => Text("$count")),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => count ++,
      ));
}
  1. 路由管理
typescript 复制代码
/// 全局配置路由及初始化路由
return GetMaterialApp(
  ...
  getPages: PageManager.pages, /// 维护的所有页面
  initialRoute: RouteManager.splashPage, /// 初始化路由
  initialBinding: SplashBinding(), /// 初始化路由页面对应的binding
  ...
);

/// 带参数页面跳转
Get.toNamed(RouteManager.tutorialPage, arguments: category);

/// 参数获取
@override
void onInit() {
  super.onInit();
  if (Get.arguments is Category) {
    state.category = Get.arguments;
    state.title.value = state.category.chapterName ?? "";
  }
}
  1. 主题管理
less 复制代码
/// 全局配置
return GetMaterialApp(
  ...
  theme: ThemeData.light().copyWith(extensions: [lightColorData]), // 浅色主题
  darkTheme: ThemeData.dark().copyWith(extensions: [darkColorData]), // 深色主题
  ...
);

/// 需要动态切换
Get.changeTheme(ThemeData.light().copyWith(extensions: [lightColorData]));
  1. 多语言管理:配合上述get_cli自动生成的多语言文本,结合getx实现多语言
less 复制代码
/// 全局配置语言,跟随系统
@override
Widget build(BuildContext context) {
  return GetMaterialApp(
    ...
    translationsKeys: translation.AppTranslation.translations, /// get_cli脚本生成的语言文本
    localizationsDelegates: const [
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate,
    ],
    supportedLocales: const [
      Locale('zh', 'CN'), /// 简体中文
      Locale('en', 'US'), /// 英文
    ], /// 支持的语言列表
    locale: Get.deviceLocale, /// 跟随手机系统语言
    fallbackLocale: const Locale('zh', 'CN'), /// 找不到指定语言时默认的语言(兜底)
    ...
  );
}

/// 需要动态切换
var locale = Locale('en', 'US'); 
Get.updateLocale(locale);
四、三方开源库使用(ps:flutter生态还是很好的,该有的开源库应有尽有)

bot_toast | Flutter package:基于该库实现全局loading

php 复制代码
/// 需要在app全局初始化
@override
Widget build(BuildContext context) {
  final botToastBuilder = BotToastInit();
  return GetMaterialApp(
    ...
    navigatorObservers: [
      BotToastNavigatorObserver(),
    ],
    builder: (BuildContext context, Widget? child) {
      return botToastBuilder(
          context,
          child:...);
    },
  );
}

/// 封装使用
CancelFunc showCommonLoading({
    String loadingText = "",
    Alignment? align = Alignment.center,
    crossPage = true,
    backButtonBehavior = BackButtonBehavior.ignore,
    bool clickClose = false,
    VoidCallback? onClose,
    Color? barrierColor,
    Color? backgroundColor,
    Color? circleColor,
    BoxConstraints? constraints,
    TextStyle? style,
  }) {
    return BotToast.showCustomLoading(
      align: align,
      onClose: onClose,
      clickClose: clickClose,
      backButtonBehavior: backButtonBehavior,
      crossPage: crossPage,
      backgroundColor: barrierColor ?? Colors.transparent,
      toastBuilder: (f) {
        return CommonLoading(
          loadingText: loadingText,
          backgroundColor: backgroundColor,
          circleColor: circleColor,
          constraints: constraints,
          style: style,
        );
      },
      animationDuration: const Duration(milliseconds: 250),
      animationReverseDuration: const Duration(milliseconds: 200),
    );
  }
}

oktoast | Flutter package:实现toast功能

less 复制代码
/// 需要在app初始化
@override
Widget build(BuildContext context) {
  return GetMaterialApp(
    builder: (BuildContext context, Widget? child) {
      return botToastBuilder(
          context,
          Material(
            elevation: 0,
            color: Colors.transparent,
            child: OKToast(
              child: child!,
            ),
          ));
    },
  );

/// 基本使用
showToast(LocaleKeys.username_hint.tr);

mmkv | Flutter package:本地持久化,应该大家都很熟悉啦~

event_bus | Dart package:全局事件监听

easy_refresh | Flutter package:下拉刷新上拉加载更多组件

webview_flutter | Flutter package:浏览器

相关推荐
2501_9400940218 小时前
emu系列模拟器最新汉化版 安卓版 怀旧游戏模拟器全集附可运行游戏ROM
android·游戏·安卓·模拟器
下位子18 小时前
『OpenGL学习滤镜相机』- Day9: CameraX 基础集成
android·opengl
参宿四南河三20 小时前
Android Compose SideEffect(副作用)实例加倍详解
android·app
火柴就是我21 小时前
mmkv的 mmap 的理解
android
没有了遇见21 小时前
Android之直播宽高比和相机宽高比不支持后动态获取所支持的宽高比
android
shenshizhong1 天前
揭开 kotlin 中协程的神秘面纱
android·kotlin
vivo高启强1 天前
如何简单 hack agp 执行过程中的某个类
android
沐怡旸1 天前
【底层机制】 Android ION内存分配器深度解析
android·面试
你听得到111 天前
肝了半个月,我用 Flutter 写了个功能强大的图片编辑器,告别image_cropper
android·前端·flutter
KevinWang_1 天前
Android 原生 app 和 WebView 如何交互?
android