Skip to content

Commit

Permalink
perf(home): improve performance in home view
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhuJHua committed Aug 26, 2024
1 parent 68d7dcc commit becd739
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 138 deletions.
12 changes: 11 additions & 1 deletion lib/common/values/view_mode.dart
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
enum ViewMode { list, calendar }
enum ViewModeType {
list(0, 'ListView'),
calendar(1, 'CalendarView');

const ViewModeType(this.number, this.value);

final int number;
final String value;

static ViewModeType getType(int number) => ViewModeType.values.firstWhere((e) => e.number == number);
}
1 change: 0 additions & 1 deletion lib/components/home_tab_view/home_tab_view_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class HomeTabViewComponent extends StatelessWidget {
return MasonryGridView.builder(
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 440),
padding: const EdgeInsets.symmetric(horizontal: 4.0),
shrinkWrap: true,
itemBuilder: (context, index) {
final aspect = state.diaryList.value[index].aspect;
//如果是横图,显示大卡片,竖图或者没有图显示小卡片
Expand Down
39 changes: 8 additions & 31 deletions lib/pages/home/home_logic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin {
void onReady() {
// TODO: implement onReady

var innerController = state.nestedScrollKey.currentState!.innerController;

innerController.addListener(() async {
state.innerController.addListener(() async {
if (!tabController.indexIsChanging) {
double offset = innerController.offset;
double maxScrollExtent = innerController.position.maxScrollExtent;
double offset = state.innerController.offset;
double maxScrollExtent = state.innerController.position.maxScrollExtent;
// 显示或隐藏“回到顶部”按钮
state.isToTopShow.value = offset > 0;
// 分页加载
Expand All @@ -51,8 +49,6 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin {
}
}
});

initTabListener();
super.onReady();
}

Expand All @@ -64,23 +60,9 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin {
super.onClose();
}

void initTabListener() {
//监听tab滚动,切换时回到顶部

tabController.addListener(() async {
if (!tabController.indexIsChanging) {
var outerController = state.nestedScrollKey.currentState!.outerController;
if (outerController.offset != .0) {
await outerController.animateTo(0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut);
//标记为变化结束
}
}
});
}

Future<void> toTop() async {
var outerController = state.nestedScrollKey.currentState!.outerController;
await outerController.animateTo(0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut);
await state.innerController.animateTo(0.0, duration: const Duration(milliseconds: 100), curve: Curves.easeInOut);
await state.outerController.animateTo(0.0, duration: const Duration(milliseconds: 100), curve: Curves.easeInOut);
}

//初始化分类tab
Expand All @@ -101,11 +83,7 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin {
if (state.categoryList.length < currentIndex) {
currentIndex = state.categoryList.length;
}
//移出原有监听器
tabController.removeListener(initTabListener);
tabController = TabController(length: state.categoryList.length + 1, vsync: this, initialIndex: currentIndex);
//重新开始监听
initTabListener();
maxScrollExtentSet = {};
//添加帧回调保证对应logic已经被创建
WidgetsBinding.instance.addPostFrameCallback((_) async {
Expand Down Expand Up @@ -147,9 +125,9 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin {
}

//切换视图模式
Future<void> changeViewMode(ViewMode viewMode) async {
state.viewMode.value = viewMode.name;
await Utils().prefUtil.setValue<String>('homeViewMode', viewMode.name);
Future<void> changeViewMode(ViewModeType viewModeType) async {
state.viewModeType.value = viewModeType;
await Utils().prefUtil.setValue<int>('homeViewMode', viewModeType.number);
}

//新增一篇日记
Expand All @@ -161,6 +139,5 @@ class HomeLogic extends GetxController with GetTickerProviderStateMixin {
fabAnimationController.reset();
state.isFabExpanded.value = false;
await updateDiary();
//点击添加按钮后新增一篇日记
}
}
9 changes: 7 additions & 2 deletions lib/pages/home/home_state.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mood_diary/common/models/isar/category.dart';
import 'package:mood_diary/common/values/view_mode.dart';
import 'package:mood_diary/utils/utils.dart';

class HomeState {
Expand All @@ -13,8 +14,12 @@ class HomeState {
//主滚动列表key
late GlobalKey<NestedScrollViewState> nestedScrollKey;

ScrollController get innerController => nestedScrollKey.currentState!.innerController;

ScrollController get outerController => nestedScrollKey.currentState!.outerController;

//视图模式状态
late RxString viewMode;
late Rx<ViewModeType> viewModeType;

//fab展开状态
late RxBool isFabExpanded;
Expand All @@ -28,7 +33,7 @@ class HomeState {
HomeState() {
isFabExpanded = false.obs;
isToTopShow = false.obs;
viewMode = Utils().prefUtil.getValue<String>('homeViewMode')!.obs;
viewModeType = ViewModeType.getType(Utils().prefUtil.getValue<int>('homeViewMode')!).obs;
selectDateTime = <DateTime>[].obs;
categoryList = Utils().isarUtil.getAllCategory().obs;
customTitleName = Utils().prefUtil.getValue<String>('customTitleName')!;
Expand Down
204 changes: 103 additions & 101 deletions lib/pages/home/home_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,19 @@ class HomePage extends StatelessWidget {
);
});
return TabBarView(
controller: logic.tabController,
physics: const NeverScrollableScrollPhysics(),
children: allView,
);
controller: logic.tabController, physics: const NeverScrollableScrollPhysics(), children: allView);
}

Widget buildModal() {
return AnimatedBuilder(
animation: logic.fabAnimation,
builder: (context, child) {
return state.isFabExpanded.value
? ModalBarrier(
color: Color.lerp(Colors.transparent, Colors.black54, logic.fabAnimation.value),
)
: const SizedBox.shrink();
});
}

return GetBuilder<HomeLogic>(
Expand All @@ -67,109 +76,102 @@ class HomePage extends StatelessWidget {
return Scaffold(
drawer: const SideBarComponent(),
drawerEnableOpenDragGesture: false,
body: Obx(() {
return Stack(
children: [
NestedScrollView(
key: state.nestedScrollKey,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
title: Tooltip(
message: '侧边栏',
child: InkWell(
onTap: () {
Scaffold.of(context).openDrawer();
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
state.customTitleName.isNotEmpty ? state.customTitleName : i18n.appName,
overflow: TextOverflow.ellipsis,
),
body: Stack(
children: [
NestedScrollView(
key: state.nestedScrollKey,
headerSliverBuilder: (context, _) {
return [
SliverAppBar(
title: Tooltip(
message: '侧边栏',
child: InkWell(
onTap: () {
Scaffold.of(context).openDrawer();
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
state.customTitleName.isNotEmpty ? state.customTitleName : i18n.appName,
overflow: TextOverflow.ellipsis,
),
const Icon(Icons.chevron_right)
],
),
),
const Icon(Icons.chevron_right)
],
),
),
automaticallyImplyLeading: false,
actions: [
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
showDragHandle: true,
useSafeArea: true,
builder: (context) {
return const SearchSheetComponent();
});
},
icon: const Icon(Icons.search),
tooltip: '搜索',
),
PopupMenuButton(
offset: const Offset(0, 46),
tooltip: '更多',
itemBuilder: (context) {
return <PopupMenuEntry<String>>[
CheckedPopupMenuItem(
checked: state.viewMode.value == ViewMode.list.name,
onTap: () async {
await logic.changeViewMode(ViewMode.list);
},
child: Text(i18n.homeViewModeList),
),
CheckedPopupMenuItem(
checked: state.viewMode.value == ViewMode.calendar.name,
onTap: () async {
await logic.changeViewMode(ViewMode.calendar);
},
child: Text(i18n.homeViewModeCalendar),
),
];
},
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(46.0),
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: logic.tabController,
isScrollable: true,
dividerHeight: .0,
tabAlignment: TabAlignment.start,
indicatorSize: TabBarIndicatorSize.tab,
splashFactory: NoSplash.splashFactory,
indicator:
ShapeDecoration(shape: const StadiumBorder(), color: colorScheme.secondaryContainer),
indicatorWeight: .0,
indicatorPadding: const EdgeInsets.all(8.0),
tabs: buildTabBar(),
),
),
automaticallyImplyLeading: false,
actions: [
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
showDragHandle: true,
useSafeArea: true,
builder: (context) {
return const SearchSheetComponent();
});
},
icon: const Icon(Icons.search),
tooltip: '搜索',
),
PopupMenuButton(
offset: const Offset(0, 46),
tooltip: '更多',
itemBuilder: (context) {
return <PopupMenuEntry<String>>[
CheckedPopupMenuItem(
checked: state.viewModeType.value == ViewModeType.list,
onTap: () async {
await logic.changeViewMode(ViewModeType.list);
},
child: Text(i18n.homeViewModeList),
),
CheckedPopupMenuItem(
checked: state.viewModeType.value == ViewModeType.calendar,
onTap: () async {
await logic.changeViewMode(ViewModeType.calendar);
},
child: Text(i18n.homeViewModeCalendar),
),
];
},
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(46.0),
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: logic.tabController,
isScrollable: true,
dividerHeight: .0,
tabAlignment: TabAlignment.start,
indicatorSize: TabBarIndicatorSize.tab,
splashFactory: NoSplash.splashFactory,
indicator:
ShapeDecoration(shape: const StadiumBorder(), color: colorScheme.secondaryContainer),
indicatorWeight: .0,
indicatorPadding: const EdgeInsets.all(8.0),
tabs: buildTabBar(),
),
),
),
];
},
body: state.viewMode.value == ViewMode.list.name ? buildListView() : buildDatePicker(),
),
//如果fab打开了,显示一个蒙层
if (state.isFabExpanded.value) ...[
AnimatedBuilder(
animation: logic.fabAnimation,
builder: (context, child) {
return ModalBarrier(
color: Color.lerp(Colors.transparent, Colors.black54, logic.fabAnimation.value),
);
})
]
],
);
}),
)
];
},
body: switch (state.viewModeType.value) {
ViewModeType.list => buildListView(),
ViewModeType.calendar => buildDatePicker()
},
),
//如果fab打开了,显示一个蒙层
buildModal(),
],
),
floatingActionButton: AnimatedBuilder(
animation: logic.fabAnimation,
builder: (context, child) {
Expand Down
4 changes: 2 additions & 2 deletions lib/utils/data/pref.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:mood_diary/common/values/view_mode.dart';
import 'package:mood_diary/utils/utils.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Expand Down Expand Up @@ -65,7 +66,6 @@ class PrefUtil {
Future<void> initPref() async {
_prefs = await SharedPreferencesWithCache.create(
cacheOptions: const SharedPreferencesWithCacheOptions(allowList: allowList));

// 首次启动
var firstStart = _prefs.getBool('firstStart') ?? true;
await _prefs.setBool('firstStart', firstStart);
Expand Down Expand Up @@ -103,7 +103,7 @@ class PrefUtil {
await _prefs.setBool('getWeather', _prefs.getBool('getWeather') ?? false);
await _prefs.setInt('startTime', _prefs.getInt('startTime') ?? DateTime.now().millisecondsSinceEpoch);
await _prefs.setString('customTitleName', _prefs.getString('customTitleName') ?? '');
await _prefs.setString('homeViewMode', _prefs.getString('homeViewMode') ?? 'list');
await _prefs.setInt('homeViewMode', _prefs.getInt('homeViewMode') ?? ViewModeType.list.number);
}

Future<void> setValue<T>(String key, T value) async {
Expand Down

0 comments on commit becd739

Please sign in to comment.