jan*_*oth 2 controller flutter getx
我正在开发一个应用程序,它有一个五页的底部导航栏。我使用 getx。在第一页,我列出了数据。我的问题是,当我从数据库手动更改数据(底部导航栏中的第一页)然后我越过页面时,回到第一页我看不到更改。
控制器;
class ExploreController extends GetxController {
var isLoading = true.obs;
var articleList = List<ExploreModel>().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();
}
}
Run Code Online (Sandbox Code Playgroud)
和我的用户界面;
body: SafeArea(
child: Column(
children: <Widget>[
Header(),
Expanded(
child: GetX<ExploreController>(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) {
Run Code Online (Sandbox Code Playgroud)
GetX 不知道/看不到数据库数据何时更改/更新。
您需要告诉 GetX 在适当的时候重建。
如果您将 GetXobservables与GetX或Obx小部件一起使用,那么您只需为您的observable字段分配一个新值。当obs值改变时会发生重建。
如果您将 GetX 与 一起使用GetBuilder<MyController>,则需要在update()内部调用方法MyController来重建GetBuilder<MyController>小部件。
下面的解决方案使用 GetX 控制器(即TabX)来:
保持应用程序状态:
tabPages)selectedIndex)公开一种更改活动/可见选项卡的方法 ( onItemTapped())
这个方法TabX在 GetXController里面。
调用时,它将:
FakeDB)update() void onItemTapped(int index) {
selectedIndex = index;
db.insertViewedPage(index); // simulate database update while tabs change
update(); // ? rebuilds any GetBuilder<TabX> widget
}
Run Code Online (Sandbox Code Playgroud)
将整个代码复制/粘贴到您的应用程序中的 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<int> 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<Widget> tabPages;
@override
void onInit() {
super.onInit();
tabPages = <Widget>[
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<TabX> widget
// ? update() is like setState() to anything inside a GetBuilder using *this*
// controller, i.e. GetBuilder<TabX>
// Other GetX controllers are not affected. e.g. GetBuilder<BlahX>, 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<TabX>(
builder: (tx) => tx.tabPages.elementAt(tx.selectedIndex)
),
),
/// ? BottomNavBar's highlighted/active item, rebuilt by GetBuilder when
/// ? TabX.onItemTapped() called
bottomNavigationBar: GetBuilder<TabX>(
builder: (tx) => BottomNavigationBar(
items: const <BottomNavigationBarItem>[
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,
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
这里不需要 GetBuilder,因为它不适用于可观察变量。您也不需要在 fetchArticles 函数中调用 update(),因为它仅适用于 GetBuilder 和不可观察的变量。
因此,您有 2 个用于更新 UI 的小部件(GetBuilder 和 Obx),它们都遵循相同的控制器,而您所需要的只是 OBX。所以 Rahuls 的答案是有效的,或者您可以将 Obx 保留在适当的位置,摆脱 GetBuilder 并在构建方法的开头声明并初始化控制器。
final exploreController = Get.put(ExploreController());
Run Code Online (Sandbox Code Playgroud)
然后使用 OBX 小部件中初始化的控制器作为 Expanded 的子控制器。
Obx(() => exploreController.isLoading.value
? Center(
child:
SpinKitChasingDots(color: Colors.deepPurple[600], size: 40),
)
: ListView.separated(
padding: EdgeInsets.all(12),
itemCount: exploreController.articleList.length,
separatorBuilder: (BuildContext context, int index) {},
),
)
Run Code Online (Sandbox Code Playgroud)
小智 5
感谢@Baker 的正确答案。但是,如果您有一个列表并且在 viewModel 中并且想要更新该列表,只需list.refresh()在列表更新时使用
RxList<Models> myList = <Models>[].obs;
Run Code Online (Sandbox Code Playgroud)
添加或插入数据时,如下所示:
myList.add(newItem);
myList.refresh();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15220 次 |
| 最近记录: |