任务 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);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
**Android精讲视频学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!
**任何市场都是优胜略汰适者生存,只要你技术过硬,到哪里都不存在饱和不饱和的问题,所以重要的还是提升自己。懂得多是自己的加分项 而不是必须项。门槛高了只能证明这个市场在不断成熟化!**另外一千个读者就有一千个哈姆雷特,所以以上只是自己的关键,不喜勿喷!
如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。欢迎关注会持续更新和分享的。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
…(img-9EYyP0zC-1712720650104)]
【Android部分高级架构视频学习资源】
**Android精讲视频学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!
**任何市场都是优胜略汰适者生存,只要你技术过硬,到哪里都不存在饱和不饱和的问题,所以重要的还是提升自己。懂得多是自己的加分项 而不是必须项。门槛高了只能证明这个市场在不断成熟化!**另外一千个读者就有一千个哈姆雷特,所以以上只是自己的关键,不喜勿喷!
如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。欢迎关注会持续更新和分享的。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-2fYp9wQp-1712720650104)]