作者:唤起 | 来源:互联网 | 2023-09-15 01:42
我正在开发一个应用程序,它有一个五页的底部导航栏。我使用getx。在第一页,我列出了数据。我的问题是,当我从数据库手动更改数据(底部导航栏中的第一页)然后我越过页面时,回到第一页我看不到
我正在开发一个应用程序,它有一个五页的底部导航栏。我使用 getx。在第一页,我列出了数据。我的问题是,当我从数据库手动更改数据(底部导航栏中的第一页)然后我越过页面时,回到第一页我看不到更改。
控制器;
class ExploreController extends GetxController {
var isLoading = true.obs;
var articleList = List().obs;
@override
void onInit() {
fetchArticles();
super.onInit();
}
void fetchArticles() async {
try {
isLoading(true);
var articles = await ApiService.fetchArticles();
if (articles != null) {
//articleList.clear();
articleList.assignAll(articles);
}
} finally {
isLoading(false);
}
update();
}
}
和我的用户界面;
body: SafeArea(
child: Column(
children: [
Header(),
Expanded(
child: GetX(builder: (exploreController) {
if (exploreController.isLoading.value) {
return Center(
child: SpinKitChasingDots(
color: Colors.deepPurple[600], size: 40),
);
}
return ListView.separated(
padding: EdgeInsets.all(12),
itemCount: exploreController.articleList.length,
separatorBuilder: (BuildContext context, int index) {
回答
GetX 不知道/看不到数据库数据何时更改/更新。
您需要告诉 GetX 在适当的时候重建。
如果您将 GetXobservables
与GetX
或Obx
小部件一起使用,那么您只需为您的observable
字段分配一个新值。当obs
值改变时会发生重建。
如果您将 GetX 与 一起使用GetBuilder
,则需要在update()
内部调用方法MyController
来重建GetBuilder
小部件。
下面的解决方案使用 GetX 控制器(即TabX
)来:
保持应用程序状态:
- 所有选项卡的列表 (
tabPages
)
- 哪个 Tab 处于活动状态 (
selectedIndex
)
公开一种更改活动/可见选项卡的方法 ( onItemTapped()
)
OnItemTapped()
这个方法TabX
在 GetXController里面。
调用时,它将:
- 设置哪个选项卡可见
- 将查看的选项卡保存到数据库 (
FakeDB
)
- 使用重建任何 GetBuilder 小部件
update()
void onItemTapped(int index) {
selectedIndex = index;
db.insertViewedPage(index); // simulate database update while tabs change
update(); // ? rebuilds any GetBuilder widget
}
完整示例
将整个代码复制/粘贴到您的应用程序中的 dart 页面中,以查看有效的 BottomNavigationBar 页面。
此选项卡式/BottomNavigationBar 示例取自
https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html,
但已编辑为使用 GetX。
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyTabHomePage(),
);
}
}
class FakeDB {
List viewedPages = [0];
void insertViewedPage(int page) {
viewedPages.add(page);
}
}
/// BottomNavigationBar page converted to GetX. Original StatefulWidget version:
/// https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html
class TabX extends GetxController {
TabX({this.db});
final FakeDB db;
int selectedIndex = 0;
static const TextStyle optiOnStyle=
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
List tabPages;
@override
void onInit() {
super.onInit();
tabPages = [
ListViewTab(db),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
}
/// INTERESTING PART HERE ? ************************************
void onItemTapped(int index) {
selectedIndex = index;
db.insertViewedPage(index); // simulate database update while tabs change
update(); // ? rebuilds any GetBuilder widget
// ? update() is like setState() to anything inside a GetBuilder using *this*
// controller, i.e. GetBuilder
// Other GetX controllers are not affected. e.g. GetBuilder, not affected
// by this update()
// Use async/await above if data writes are slow & must complete before updating widget.
// This example does not.
}
}
/// REBUILT when Tab Page changes, rebuilt by GetBuilder in MyTabHomePage
class ListViewTab extends StatelessWidget {
final FakeDB db;
ListViewTab(this.db);
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: db.viewedPages.length,
itemBuilder: (context, index) =>
ListTile(
title: Text('Page Viewed: ${db.viewedPages[index]}'),
),
);
}
}
class MyTabHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
Get.put(TabX(db: FakeDB()));
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
/// ? Tab Page currently visible - rebuilt by GetBuilder when
/// ? TabX.onItemTapped() called
child: GetBuilder(
builder: (tx) => tx.tabPages.elementAt(tx.selectedIndex)
),
),
/// ? BottomNavBar's highlighted/active item, rebuilt by GetBuilder when
/// ? TabX.onItemTapped() called
bottomNavigationBar: GetBuilder(
builder: (tx) => BottomNavigationBar(
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: tx.selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: tx.onItemTapped,
),
),
);
}
}
回答
感谢@Baker 的正确答案。但是,如果您有一个列表并且在 viewModel 中并且想要更新该列表,只需list.refresh()
在列表更新时使用
RxList myList = [].obs;
添加或插入数据时,如下所示:
myList.add(newItem);
myList.refresh();