GetX项目级实战

在欢迎页会注入全局的依赖,然后判断是否登录,对应不同的导航:

@override

void onReady() async {

super.onReady();

await GloabConfig.init();

await DenpendencyInjection.init();

LoginProvider loginProvider = Get.find();

print(loginProvider);

// 如果未登录就登录

// 如果已登录就去task页面

if (loginProvider.isLogin()) {

Get.offNamed(Routes.TASK);

} else {

Get.offNamed(Routes.LOGIN);

}

}

}

Task 列表


主页实现了底部导航和嵌入式FloatingActionButtonLocation,没有任务的时候会弹出使用引导。点击加号可以添加任务。因为 api 是分页的,所以也做了分页处理。

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(title: Text(‘My Task’)),

body: Body(),

floatingActionButton: FloatingActionButton(

onPressed: () {

Get.toNamed(Routes.TASK_ADD);

},

child: Icon(Icons.add),

),

floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,

bottomNavigationBar: BottomAppBar(

shape: CircularNotchedRectangle(),

child: Row(

mainAxisAlignment: MainAxisAlignment.spaceBetween,

children: [

IconButton(

icon: Icon(Icons.calendar_today_sharp),

onPressed: () {

Get.toNamed(Routes.TASK_MOTHLY);

},

),

IconButton(

icon: Icon(Icons.settings),

onPressed: () {

Get.toNamed(Routes.PROFILE);

},

),

],

),

),

);

}

}

任务 item可以点击进入详情和侧滑,有两个侧滑菜单,编辑和删除,对应不同的功能,圆形的checkbox可以完成任务,任务标题和时间在完成时会有删除线。

GetView 就是封装的StatelessWidget,内部有一个 get方法便捷的获取注入的controller,这样连获取的步骤都能省略。

增加和编辑


对应的标题是必须项,描述可以为空,时间是默认当前,优先级有高低中三个,默认是中。

选择日期会弹出日历你,采用局部刷新,提高性能,update([updateDateId])函数的参数是一个 id,只会刷新对应 id 的 GetBuilder,并且 GetX 不受 InheritedWidget的限制,所以可以在任意地方引用未被内存回收的 Controller,所以可以在编辑页面,让列表页也同时刷新。

void handleDatePicker() async {

final datePick = await showDatePicker(

context: Get.context,

firstDate: DateTime(2000),

initialDate: _dateTime,

lastDate: DateTime(2100));

if (datePick != null && datePick != _dateTime) {

_dateTime = datePick;

task.dateStr = _dateTime.format();

dateTimeController.text = task.dateStr;

update([updateDateId]);

}

}

void submit() async {

if (formKey.currentState.validate()) {

formKey.currentState.save();

try {

Get.loading();

await _taskRepository.updateTask(task);

Get.dismiss();

// 刷新列表页

Get.find().update();

// controller.updateTask(task);

Get.back();

} catch (e) {

print(e);

Get.dismiss();

Get.snackbar(‘Error’, e.toString());

}

}

}

月份视图


月份视图用了table_calendar包,这个包功能强大,可以定制日历视图。默认显示两周,点击月份展开四周的月份视图。可以按日期筛选出任务。这里的任务可以点击进入详情和点击checkbox更改状态。

TableCalendar(

onDaySelected: (DateTime day, _, __) {

controller.selectedDate(day);

},

calendarController: controller.calendarController,

startingDayOfWeek: StartingDayOfWeek.monday,

initialCalendarFormat: CalendarFormat.week,

calendarStyle: CalendarStyle(

selectedColor: Theme.of(context).accentColor,

),

)

这里更改状态后,同样可以拿到列表页的Controller去更新列表页:

modifyTaskStatus(Task task) async {

try {

TaskController taskController = Get.find();

await taskController.modifyTaskStatus(task);

} catch (e) {}

update();

}

个人中心


个人中心是一个静态页面,最下面展示了我写的 GetX 的 demo 截图。点击放大的功能放在迭代里做吧。

这里藏有福利,一个漂亮的二次元萌妹子。

扩展函数


在 utils文件夹下写了两个扩展函数,扩展了日期格式化和基于 GetX 的全局加载框。

extension DateExtension on DateTime {

String format() {

return formatDate(this, [

yyyy,

‘-’,

mm,

‘-’,

dd,

]);

}

}

extension GetExtension on GetInterface {

dismiss() {

if (Get.isDialogOpen) {

Get.back();

}

}

loading() {

if (Get.isDialogOpen) {

Get.back();

}

Get.dialog(LoadingDialog());

}

}

使用也很简单,但不要忘了要导入扩展函数类:

dateTime.format();

Get.loading();

。。。。。。

Get.dismiss();

GetService


GetService 我的理解是类似服务,比如 SharedPreferences、Database,还有需要异步初始化的类,放在这里注入非常合适:

TaskDao init() {

TaskDatabase database = TaskDatabase();

return TaskDao(database);

}

}

class AppSpController extends GetxService {

Future init() async {

return await SharedPreferences.getInstance();

}

}

同步的就用同步方法注入:

// 数据库

Get.put(TaskDaoController().init());

异步的用异步方法注入:

// shared_preferences

await Get.putAsync(() => AppSpController().init());

数据库 moor 的使用


Android 通过 room 给开发带来的便利,用过的都知道。moor 就是 Flutter 上的 room。

Moor 使用 Dart 的源代码生成器生成代码,我们可以用函数式的调用操作数据库。这也是需要 moor_generator 依赖项以及 build_runner 的原因。

moor 优点之一是我们可以完全使用 Dart 操作数据库,而不必写数据库语句。这也适用于定义SQL表。创建一个表示 table 的类即可。

class Tasks extends Table {

// 可空类型

IntColumn get completeDate => integer().nullable()();

TextColumn get completeDateStr => text().nullable()();

TextColumn get content => text().nullable()();

// 为空自动生成默认值

IntColumn get date =>

integer().clientDefault(() => DateTime.now().millisecondsSinceEpoch)();

// 为空自动生成默认值

TextColumn get dateStr =>

text().nullable().clientDefault(() => DateTime.now().format())();

// 主键

IntColumn get id => integer().nullable().autoIncrement()();

// 为空自动生成默认值

IntColumn get priority => integer().nullable().withDefault(Constant(0))();

// 为空自动生成默认值

IntColumn get status => integer().nullable().withDefault(Constant(0))();

TextColumn get title => text()();

IntColumn get type => integer().withDefault(Constant(0))();

IntColumn get userId => integer().nullable()();

}

@UseMoor(tables: [Tasks], daos: [TaskDao])

class TaskDatabase extends _$TaskDatabase {

// we tell the database where to store the data with this constructor

TaskDatabase() : super(_openConnection());

// you should bump this number whenever you change or add a table definition. Migrations

// are covered later in this readme.

@override

int get schemaVersion => 1;

}

LazyDatabase _openConnection() {

// the LazyDatabase util lets us find the right location for the file async.

return LazyDatabase(() async {

// put the database file, called db.sqlite here, into the documents folder

// for your app.

final dbFolder = await getApplicationDocumentsDirectory();

final file = File(join(dbFolder.path, ‘db.sqlite’));

return VmDatabase(file);

});

}

数据库操作写在这里也可以,但是会显得臃肿,moor 还提供 Dao ,把操作放在 Dao 类是个好习惯:

@UseDao(tables: [Tasks])

class TaskDao extends DatabaseAccessor with _$TaskDaoMixin {

TaskDao(TaskDatabase db) : super(db);

/// 获取全部

Future<List> get getAllTasks => select(tasks).get();

///imit查询来限制返回的结果数量

///offset偏移量

Future<List> getTasks(int limit, {int offset}) {

return (select(tasks)…limit(limit, offset: offset)).get();

}

///imit查询来限制返回的结果数量

///offset偏移量

Future<List> getTasksWithDateStr(String dateStr) {

return (select(tasks)…where((e) => e.dateStr.equals(dateStr))).get();

}

/// 获取单个数据

/// 没必要用list

Future getTaskById(int id) {

return (select(tasks)…where((t) => t.id.equals(id))).getSingle();

}

Future updateTask(Task entry) {

TasksCompanion();

return update(tasks).replace(entry);

}

Future createOrUpdateUser(String title,

{String content, String date, int type = 0, int priority = 0}) {

return into(tasks).insertOnConflictUpdate(TasksCompanion(

title: Value(title),

content: Value(content),

dateStr: Value(date),

type: Value(type),

priority: Value(priority),

));

}

Future createTask(TasksCompanion task) async {

var id = await into(tasks).insertOnConflictUpdate(task);

return getTaskById(id);

}

/// 批量插入

Future insertMultipleTasks(List entries) async {

await batch((batch) {

batch.insertAll(tasks, entries);

});

}

Future deleteTaskById(int id) {

return (delete(tasks)…where((t) => t.id.equals(id))).go();

}

Future deleteTask(Task entry) {

return delete(tasks).delete(entry);

}

Future modifyStatusByid(int id, int status) async {

// into(tasks).up

Task task = await getTaskById(id);

task.copyWith(

status: status,

);

await updateTask(task);

return task;

}

Future modifyTask(Task task) {

return update(tasks).replace(task);

}

/// 表中数据改变,会发生一个流

Stream<List> watchEntriesInCategory() {

return select(tasks).watch();

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
据改变,会发生一个流

Stream<List> watchEntriesInCategory() {

return select(tasks).watch();

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-t1uvzUK3-1715601126108)]

[外链图片转存中…(img-YaAtOKRC-1715601126111)]

[外链图片转存中…(img-C4Grqsbi-1715601126112)]

[外链图片转存中…(img-VEwg7X85-1715601126114)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们来实战一下 Flutter GetX。 1. 首先,我们需要在 `pubspec.yaml` 文件中添加 GetX 的依赖。 ```yaml dependencies: flutter: sdk: flutter get: ^4.6.1 ``` 2. 然后,我们需要在 `main.dart` 文件中引入 GetX 包,并在 `runApp` 函数中添加 `GetMaterialApp`。 ```dart import 'package:flutter/material.dart'; import 'package:get/get.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetMaterialApp( title: 'Flutter GetX Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const HomePage(), ); } } ``` 3. 接下来,我们需要创建一个 `HomePage` 类,这个类将会是我们的主页。在 `HomePage` 类中,我们将会使用 `GetX` 的 `Obx` 和 `GetBuilder` 来管理状态和更新 UI。 ```dart import 'package:flutter/material.dart'; import 'package:get/get.dart'; class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter GetX Demo'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ GetBuilder<CounterController>( builder: (controller) => Text( 'Count: ${controller.count}', style: const TextStyle(fontSize: 24), ), ), const SizedBox(height: 16), ElevatedButton( onPressed: () { final controller = Get.find<CounterController>(); controller.increment(); }, child: const Text('Increment'), ), ], ), ), ); } } class CounterController extends GetxController { var count = 0.obs; void increment() { count++; } } ``` 在这个例子中,我们使用了 `GetBuilder` 来订阅 `CounterController` 中的 `count` 变量。当 `count` 发生变化时,UI 将会自动更新。我们还使用了 `Get.find` 来获取 `CounterController` 的实例,然后调用 `increment` 方法来增加计数器的值。 4. 最后,我们需要在 `main.dart` 文件中注册 `CounterController`。 ```dart import 'package:flutter/material.dart'; import 'package:get/get.dart'; void main() { Get.put(CounterController()); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return GetMaterialApp( title: 'Flutter GetX Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const HomePage(), ); } } class HomePage extends StatelessWidget { // ... } class CounterController extends GetxController { // ... } ``` 在这个例子中,我们使用了 `Get.put` 来注册 `CounterController`,这样我们就可以在整个应用程序中使用它了。 以上就是一个简单的 Flutter GetX 实战例子,希望能够帮助到你入门 GetX
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值