flutter getx 简单使用教程

news/2024/11/30 18:54:19/

所以Flutter使用GetX真的很不错

为什么说什么GetX好用呢?
1、依赖注入
GetX是通过依赖注入的方式,存储相应的XxxGetxController;已经脱离了InheritedWidget那一套玩法,自己手动去管理这些实例,使用场景被大大拓展
2、跨页面交互
这绝对是GetX的一个优点!对于复杂的生产环境,跨页面交互的场景,实在太常见了,GetX的跨页面交互,实现的也较为优雅
3、路由管理
GetX内部实现了路由管理,而且用起来,非常简单。
(bloc没实现路由管理,fluro的路由管理使用非常麻烦)
4、实现了全局BuildContext
5、国际化
6、主题管理
GetX的版本事
4.3.8之后的就是非空安全的版本了。
arduino复制代码# getx 状态管理框架 https://pub.flutter-io.cn/packages/get

非空安全最后一个版本(flutter 2.0之前版本)

get: ^3.26.0

空安全版本 最新版本请查看 https://pub.flutter-io.cn/packages/get

get: ^4.3.8

使用方式引入下:
vbnet复制代码dependencies: get: ^4.3.8

以上,巴拉巴拉。
以下,说事。
一、状态管理
官方的计数器换成GetX怎么实现呢
这是官方的默认计数器。
DART复制代码import ‘package:flutter/material.dart’;

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter Demo’,
theme: ThemeData(

    primarySwatch: Colors.blue,),home: const MyHomePage(title: 'Flutter Demo Home Page'),
);

}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;

@override
State createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
‘You have pushed the button this many times:’,
),
Text(
‘$_counter’,
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: ‘Increment’,
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

官方的

.
.

换成GetX
dart复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

void main() {
// runApp(const MyApp());
runApp(GetMaterialApp(home: Home()));
}
class Controller extends GetxController{
var count = 0.obs;
increment() => count++;
}

class Home extends StatelessWidget {
@override
Widget build(context) {

// 使用Get.put()实例化你的类,使其对当下的所有子路由可用。
final Controller c = Get.put(Controller());return Scaffold(// 使用Obx(()=>每当改变计数时,就更新Text()。appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),// 页面跳转跳转,稍微用上了一点点 路由管理,// 用一个简单的Get.to()即可代替Navigator.push那8行,无需上下文!body: Center(child: RaisedButton(child: Text("Go to Other"), onPressed: () => Get.to(Other()))),floatingActionButton:FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));

}
}

class Other extends StatelessWidget {
// 你可以让Get找到一个正在被其他页面使用的Controller,并将它返回给你。
final Controller c = Get.find();
@override
Widget build(context){
// 访问更新后的计数变量
return Scaffold(body: Center(child: Text(“${c.count}”)));
}
}

Home页面

.
.
Other页面

.
.
上面的代码有一下几个点需要注意下:
1、GetMaterialApp并不是修改后的MaterialApp,它只是一个预先配置的Widget,它的子组件是默认的MaterialApp。你可以手动配置,但绝对没有必要。GetMaterialApp会创建路由,注入它们,注入翻译,注入你需要的一切路由导航。如果你只用Get来进行状态管理或依赖管理,就没有必要使用GetMaterialApp。GetMaterialApp对于路由、snackbar、国际化、bottomSheet、对话框以及与路由相关的高级apis和没有上下文(context)的情况下是必要的。
2、使用GetMaterialApp,你就可以直接使用GetX的路由功能。如果不需要路由也可以不这么做。
3、我们创建了一个Controller业务逻辑类,class Controller extends GetxController。并将所有的变量,方法和控制器放在里面。另外,我们使用一个简单的".obs "使任何变量成为可观察的。这样跨页面的数据交互就方便了很多。
4、你应该也发现了,我们在other里面方式使用home页面的count的数据是如何方便。
(Get不是其他状态管理器的敌人,因为Get是一个微框架,而不仅仅是一个状态管理器,既可以单独使用,也可以与其他状态管理器结合使用。)
5、使用GetX可以忘记StatefulWidget,因为GetX自身都是有用状态的
复制代码
二、GetX的状态管理器
Get有两个不同的状态管理器:简单的状态管理器(GetBuilder)和响应式状态管理器(GetX)

简单状态管理: GetBuilder:这是一个极其轻巧的状态管理器,占用资源极少!数据变化需要手动update
响应式状态管理:当数据源变化时,将自动执行刷新组件的方法 obs。

1、简易模式状态管理 GetBuilder
DART复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

void main() {
runApp(GetMaterialApp(home: CounterEasyPage()));
}
class EasyController extends GetxController{
// 注意这里没加 obs
var count = 0;
void increase() {
++count;
// 手动更新数据
update();
}
}

class CounterEasyPage extends StatelessWidget {
@override
Widget build(context) {

// 使用Get.put()实例化你的类,使其对当下的所有子路由可用。
final EasyController easyC = Get.put(EasyController());return Scaffold(appBar: AppBar(title: const Text('计数器-简易模式')),body: Center(// 使用GetBuilder 简易模式,省内存,需要手动更新数据child: GetBuilder<EasyController>(builder: (controller) {return Text('点击了 ${controller.count} 次',style: TextStyle(fontSize: 30.0),);}),),floatingActionButton: FloatingActionButton(// 调用increase方法onPressed: () => easyC.increase(),child: Icon(Icons.add),),
);

}
}

1、runApp使用GetMaterialApp
2、写一个继承自GetxController的类,对数据的变化使用update手动更新数据
3、使用 GetBuilder 方法,实现简易模式的状态管理

关于GetBuilder方法

init:虽然上述代码没用到,但是,这个参数是存在在GetBuilder中的,因为在加载变量的时候就使用Get.put()生成了CounterEasyGetLogic对象,GetBuilder会自动查找该对象,所以,就可以不使用init参数
builder:方法参数,拥有一个入参,类型便是GetBuilder所传入泛型的类型
initState,dispose等:GetBuilder拥有StatefulWidget所有周期回调,可以在相应回调内做一些操作

.
.

.
.
2、响应式状态管理 obx obs
响应式状态管理,当数据源变化时,将自动执行刷新组件的方法
DART复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

void main() {
runApp(GetMaterialApp(home: CounterEasyPage()));
}
class EasyController extends GetxController{
// 注意使用了 obs
var count = 0.obs;
void increase() {
++count;
// 使用了obs就无需手动刷新了
}
}

class CounterEasyPage extends StatelessWidget {
@override
Widget build(context) {

// 使用Get.put()实例化你的类,使其对当下的所有子路由可用。
final EasyController easyC = Get.put(EasyController());return Scaffold(appBar: AppBar(title: const Text('计数器-响应式模式')),body: Center(// 使用响应式状态管理,自动刷新child: Obx((){return Text('点击了 ${easyC.count} 次',style: TextStyle(fontSize: 30.0),);}),),floatingActionButton: FloatingActionButton(// 调用increase方法onPressed: () => easyC.increase(),child: Icon(Icons.add),),
);

}
}

.
.

.
.

1、runApp使用GetMaterialApp
2、写一个继承自GetxController的类,变量数值后写.obs操作,是说明定义了该变量为响应式变量,当该变量数值变化时,页面的刷新方法将自动刷新。
3、无需 GetBuilder 方法。
4、基础类型,List,类都可以加.obs,使其变成响应式变量

注意点:

只有当响应式变量的值发生变化时,才会会执行刷新操作,当某个变量初始值为:“test”,再赋值为:“test”,并不会执行刷新操作
当你定义了一个响应式变量,该响应式变量改变时,包裹该响应式变量的Obx()方法才会执行刷新操作,其它的未包裹该响应式变量的Obx()方法并不会执行刷新操作

3、简单模式个相应的对比选择

响应式模式耗内存! 每一个响应式变量,都需要生成对应的GetStream,占用资源大于基本数据类型,会对内存造成一定压力
简易模式省内存,GetBuilder内部实际上是对StatefulWidget的封装,所以占用资源极小。

一般来说,对于大多数场景都是可以使用响应式变量的。
但是,在一个包含了大量对象的List,都使用响应式变量,将生成大量的GetStream,必将对内存造成较大的压力,该情况下,就要考虑使用简单状态管理了
总的来说:推荐GetBuilder和update配合的写法

定义obx变量的3种方式

DART复制代码// 第一种 使用 Rx{Type}
// final name = RxString(‘’);
// final isLogged = RxBool(false);
// final count = RxInt(0);
// final balance = RxDouble(0.0);
// final items = RxList([]);
// final myMap = RxMap<String, int>({});

// 第二种是使用 Rx,规定泛型 Rx。
// final name = Rx(‘’);
// final isLogged = Rx(false);
// final count = Rx(0);
// final balance = Rx(0.0);
// final number = Rx(0)
// final items = Rx<List>([]);
// final myMap = Rx<Map<String, int>>({});
// 自定义类 - 可以是任何类
// final user = Rx();

// 第三种更实用、更简单、更可取的方法,只需添加 .obs 作为value的属性。
// final name = ‘’.obs;
// final isLogged = false.obs;
// final count = 0.obs;
// final balance = 0.0.obs;
// final number = 0.obs;
// final items = [].obs;
// final myMap = <String, int>{}.obs;
// 自定义类 - 可以是任何类
// final user = User().obs;

三、路由管理和跨页面交互
GetX的路由,可以分为 简单路由 和 命名路由。
在GetX的路由世界,完全可以忘记context。
四.1、普通路由
.
普通路由 打开新页面
GetX方式: Get.to(NextScreen());

原生路由方式

DART复制代码Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return NextScreen();
},
));

.
普通路由 返回 / 关闭当前页
GetX方式: Get.Get.back();

原生路由方式

DART复制代码Navigator.pop(context);

.
普通路由 关闭当前页,打开新页面
GetX方式: Get.off(NextScreen());

原生路由方式

DART复制代码 Navigator.pushReplacement(context, MaterialPageRoute(
builder: (BuildContext context) {
return NextScreen();
},
));

普通路由 打开新页面并删除之前的所有路由
GetX方式: Get.offAll(NextScreen());

原生路由方式

DART复制代码 Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return NextScreen();
},
),
(Route route) => false,
);

普通路由 导航到新页面,在返回时接收返回数据
GetX方式:

打开时:var data = await Get.to(NextScreen());
打开的页面返回时:Get.back(result: ‘success’);

.

原生路由方式

DART复制代码 var data = await Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return NextScreen();
},
));

arduino复制代码 Navigator.pop(context, ‘success’);

.
四.2、别名路由
普通路由的使用比较简单,而别名路由在使用之前,需要先写个路由表。
往往我们都是采用别名路由。
准备工作

声明别名

DART复制代码abstract class Routes {
static const Initial = ‘/’;
static const NextScreen = ‘/NextScreen’;

}

.

注册路由表

php复制代码abstract class AppPages {
static final pages = [
GetPage(
name: Routes.Initial,
page: () => HomePage(),
),
GetPage(
name: Routes.NextScreen,
page: () => NextScreen(),
),
];
}

.

GetMaterialApp配置

less复制代码void main() {
runApp(GetMaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: ‘/’,
theme: appThemeData,
defaultTransition: Transition.fade,
getPages: AppPages.pages,
home: HomePage(),
));
}

配置好了,下面开始使用命名路由。
.
.
.
命名路由 导航到下一个页面
Get.toNamed(Routes.NextScreen);
导航到下一个页面并删除前一个页面
Get.offNamed(Routes.NextScreen);
导航到下一个页面并删除以前所有的页面
Get.offAllNamed(Routes.NextScreen);
发送数据到别名路由(非常好用)
GetX在这里接受任何东西,无论是一个字符串,一个Map,一个List,甚至一个类的实例。
Get.toNamed(Routes.NextScreen, arguments: ‘打豆豆’);
动态网页链接

动态网页链接 – 方式1

像web一样携带参数,适合前端开发的风格。
传参
vbnet复制代码Get.offAllNamed(“/NextScreen?device=phone&id=354&name=Enzo”);

.
获取参数
ini复制代码int id = Get.parameters[‘id’];
// out: 354
String name=Get.parameters[‘name’];

.
.

动态网页链接 – 方式2

定义路由别名
less复制代码 GetPage(
name: ‘/profile/:user’,
page: () => UserProfile(),
),

导航
vbnet复制代码Get.toNamed(“/profile/34954”);

说了这么多,还是来点例子比较直接。
例子一、 无参交互
GetX打开页面,关闭页面
DART复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

import ‘app_theme.dart’;

void main() {
runApp(GetMaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: ‘/’,
theme: appThemeData,
defaultTransition: Transition.fade,
getPages: AppPages.pages,
home: HomePage(),
));
}

abstract class Routes {
static const Initial = ‘/’;
static const NextScreen = ‘/NextScreen’;
}

abstract class AppPages {
static final pages = [
GetPage(
name: Routes.Initial,
page: () => HomePage(),
),
GetPage(
name: Routes.NextScreen,
page: () => NextScreen(),
),
];
}

class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(‘HomePage’),
),
body: Center(
child: RaisedButton(
child: Text(“Go to NextScreen”),
onPressed: () => Get.toNamed(Routes.NextScreen)),
),
);
}
}

class NextScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(‘NextScreen’),
),
body: Center(
child: RaisedButton(
child: Text(“返回”),
onPressed: () {
Get.back();
},
),
));
}
}

.
.
(备用:appTheme)
DART复制代码import ‘package:flutter/material.dart’;

const kPrimaryColor = Color(0xff171616);
const kPrimaryLightColor = Color(0xff151515);
const primaryDarkColor = Color(0xff1d1d1d);
const secondaryColor = Color(0xff1f1f1f);
const secondaryLightColor = Color(0xff1c1c1c);
const secondaryDarkColor = Color(0xff000000);
// const primaryTextColor = Color(0xFFF1E6FF);
// const secondaryTextColor = Color(0xFFF1E6FF);

ThemeData get appThemeData => ThemeData(
primaryColor: kPrimaryColor,
primaryColorLight: kPrimaryLightColor,
scaffoldBackgroundColor: Colors.white,
accentColor: kPrimaryColor,
appBarTheme: appBarTheme,
textTheme: const TextTheme());

AppBarTheme get appBarTheme => const AppBarTheme();

.
.
例子二、跨页面数据传输

页面1向页面2传递数据
页面2修改页面1的数据
GetX的 onReady 方法

DART复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

import ‘app_theme.dart’;

void main() {
runApp(GetMaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: ‘/’,
theme: appThemeData,
defaultTransition: Transition.fade,
getPages: AppPages.pages,
home: HomePage(),
));
}

abstract class Routes {
static const Initial = ‘/’;
static const NextScreen = ‘/NextScreen’;
}

abstract class AppPages {
static final pages = [
GetPage(
name: Routes.Initial,
page: () => HomePage(),
),
GetPage(
name: Routes.NextScreen,
page: () => NextScreen(),
),
];
}

class HomeController extends GetxController {
var count = 0;

///跳转到跨页面
void toJumpNextScreen() {
Get.toNamed(Routes.NextScreen, arguments: {‘msg’: ‘我是上个页面传递过来的数据’});
}

///跳转到跨页面
void increase() {
count = ++count;
update();
}
}

class HomePage extends StatelessWidget {
// 自身的Controller用put来获取
final homeCon = Get.put(HomeController());

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(‘HomePage’),
),
floatingActionButton: FloatingActionButton(
// 跳转新页面
onPressed: () => homeCon.toJumpNextScreen(),
child: const Icon(Icons.arrow_forward_outlined),
),

  body: Center(child: GetBuilder<HomeController>(builder: (logic) {return Text('NextScreen点击了 ${logic.count} 次',style: TextStyle(fontSize: 30.0));},),),
);

}
}

class NextScreenController extends GetxController {
var count = 0;
var msg = ‘’;

// 如果接收的数据需要刷新到界面上,请在onReady回调里面接收数据操作,
// onReady是在addPostFrameCallback回调中调用,刷新数据的操作在onReady进行
// 能保证界面是初始加载完毕后才进行页面刷新操作的
@override
void onReady() {
var map = Get.arguments;
msg = map[‘msg’];
update();

super.onReady();

}

///跳转到跨页面
void increase() {
count = ++count;
update();
}
}

class NextScreen extends StatelessWidget {
final homeController = Get.find();
final nextScreen = Get.put(NextScreenController());

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(title: Text(‘NextScreen’)),
floatingActionButton: FloatingActionButton(
onPressed: () {
homeController.increase();
nextScreen.increase();
},
child: const Icon(Icons.add),
),
body: Center(
child: Column(mainAxisSize: MainAxisSize.min, children: [
//计数显示
GetBuilder(
builder: (logic) {
return Text(‘NextScreen 点击了 ${nextScreen.count} 次’,
style: TextStyle(fontSize: 30.0));
},
),

      //传递数据GetBuilder<NextScreenController>(builder: (logic) {return Text('传递的数据:${nextScreen.msg}',style: TextStyle(fontSize: 20.0));},),]),),
);

}
}

四.3、中间件 routingCallback
在跳转前做些事情,比如判断是否登录,可以使用 routingCallback 来实现:
DART复制代码GetMaterialApp(
routingCallback: (routing) {
if(routing.current == ‘/second’){
// 如果登录。。。
}
}
)

四、GetxController生命周期方法

onInit:组件在内存分配后会被马上调用,可以在这个方法对 controller 做一些初始化工作。
onReady:适合做一些导航进入的事件,例如对话框提示、SnackBar 或异步网络请求。
onClose:在 onDelete 方法前调用、用于销毁 controller 使用的资源,例如关闭事件监听,关闭流对象,或者销毁可能造成内存泄露的对象,例如 TextEditingController,AniamtionController。也适用于将数据进行离线持久化。

DART复制代码@override
void onInit() {
// TODO: implement onInit
print(“初始化”);
super.onInit();
}

@override
void onReady() {
// TODO: implement onReady
print(“加载完成”);
super.onReady();
}

@override
void onClose() {
// TODO: implement onClose
print(“控制器被释放”);
super.onClose();
}

深入分析生命周期,可以查看 zhuanlan.zhihu.com/p/445371503
五、避开全局,单独处理 UniqueID
我们在开发的过程中会碰到一种情况,就是多个地方引用了同一个属性,但我只想单独更新某一个地方,那么就可以用UniqueID来进行区分。
第一步:应用程序入口设置
DART复制代码import ‘package:flutter/material.dart’;
import ‘package:flutter_getx_example/GetXControllerUniqueIDExample/GetXControllerUniqueIDExample.dart’;
import ‘package:get/get.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: “GetX”,
home: GetXControllerUniqueIDExample(),
);
}
}

第二步、定义控制器继承自GetxController,并且定义uniqueID
DART复制代码import ‘package:get/get.dart’;

class CountController extends GetxController {
var count = 0;

void increment() {
count++;
update([‘jimi_count’]);
}
}

第三步:实例化控制器并使用
DART复制代码
import ‘package:flutter/material.dart’;
import ‘package:flutter_getx_example/GetXControllerUniqueIDExample/CountConroller.dart’;
import ‘package:get/get.dart’;

class GetXControllerUniqueIDExample extends StatelessWidget {

CountController countController = Get.put(CountController());

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(“GetX Obx—GetXController”),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GetBuilder(
builder: (controller) {
return Text(
“计数器值为: ${controller.count}”,
style: TextStyle(color: Colors.red, fontSize: 30),
);
},
),
GetBuilder(
id: ‘jimi_count’,
builder: (controller) {
return Text(
“计数器值为: ${controller.count}”,
style: TextStyle(color: Colors.green, fontSize: 30),
);
},
),
SizedBox(height: 20,),
ElevatedButton(
onPressed: () => countController.increment(),
child: Text(“增加”))
],
),
),
);
}
}

六、GetX下的Snackbar、Dialog、BottomSheet
GetX下的 Snackbar
触发某些特定的事件后,需要弹出一则快捷消息,那么使用Snackbar则是最佳的选择
dart复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: “GetX”,
home: Scaffold(
appBar: AppBar(
title: Text(“GetX Title”),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Get.snackbar(“Snackbar 标题”, “欢迎使用Snackbar”);
},
child: Text(“显示 Snackbar”))
],
),
),
),
);
}
}

GetX下的 Dialog
dart复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: “GetX”,
home: Scaffold(
appBar: AppBar(
title: Text(“GetX Title”),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Get.defaultDialog(title: ‘标题’,content: Text(‘dialog的内容’));
},
child: Text(“显示 Dialog”))
],
),
),
),
);
}
}

GetX下的 BottomSheet
DART复制代码import ‘package:flutter/material.dart’;
import ‘package:get/get.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: “GetX”,
home: BottomSheetExample(),
);
}
}

class BottomSheetExample extends StatelessWidget {
GlobalKey _navKey = GlobalKey();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(“GetX Title”),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(onPressed: () {
Get.bottomSheet(
Container(
child: Wrap(
children: [
ListTile(
leading: Icon(Icons.wb_sunny_outlined),
title: Text(“白天模式”),
onTap: () {
Get.changeTheme(ThemeData.light());
},
),
ListTile(
leading: Icon(Icons.wb_sunny),
title: Text(“黑夜模式”),
onTap: () {
Get.changeTheme(ThemeData.dark());
},
)
],
),
)
);
}, child: Text(“Bottom Sheet”))
],
),
),
);
}
}

七、GetX的效率插件
在Android Studio上使用的插件
如果想使用插件,可以好好看下这篇文章。
juejin.cn/post/692410…

作者:J船长
链接:https://juejin.cn/post/7057519485036527623
首发:https://www.kkview.com


http://www.ppmy.cn/news/368551.html

相关文章

网络打印机不能安装驱动解决方案

情况 1.,已经安装好电脑的驱动可以使用&#xff1b; 2.新电脑驱动安装不上 解决方法 1&#xff1b;看能ping的通不&#xff08;如果ping不能&#xff09; 2. 如果不行打印测试页&#xff08;如果没有IP地址请重新设置&#xff09; 3&#xff1a;重置是很万能的(这里5分钟时…

如何安装打印机驱动

打印机是我们日常办公中接触最多的产品&#xff0c;那么新买的打印机应该如何安装驱动呢&#xff1f;今天驱动哥就来给大家介绍一下打印机驱动的安装方法。 一、分辨打印机型号 先找到相应品牌的打印机&#xff0c;具体可以从对应品牌打印机的官网下载打印机驱动程序&#xf…

win7未能成功安装驱动服务器,win7找不到驱动程序提示“未能成功安装设备驱动程序”的解决方法...

往往很多电脑无法正常使用U盘的情况&#xff0c;并不都是萝卜家园win7操作系统的问题。由于单位为了电脑安全和信息保密&#xff0c;常常会通过注册表禁用USB接口、注册表禁用U盘、屏蔽USB接口的使用等。如果win7并没有刻意去禁用USB接口等&#xff0c;也有出现U盘无法使用的情…

计算机无法安装网卡驱动,实在无法安装电脑驱动的解决办法

当我们重新安装电脑的系统之后&#xff0c;必须得给电脑安装如下的驱动程序&#xff0c;才能保证电脑能正常的运行。 &#xff21;、网卡驱动程序 &#xff22;、显卡驱动程序 &#xff23;、声卡驱动程序 如上的三个驱动程序是必须要安装的&#xff0c;这是最基本最根本的驱动…

计算机打印机副机无法打印,局域网打印机无法打印怎么办 局域网打印机无法打印解决方法...

局域网打印机为什么不能打印呢?其实连接打印机的电脑直接打印和局域网内的打印机是不一样的&#xff0c;如果直接打印机电脑可以打印&#xff0c;说明问题出在网络上。如果打印机网络接口有问题&#xff0c;也是不能再局域网内进行打印的。还有一个情况是&#xff0c;在打印机…

驱动精灵w8ndows xp sp2,惠普打印机驱动官方正式版下载,适用于winxp,win2003,winvista,win7,win8,win10,win2008,win2012-驱动精灵...

驱动说明&#xff1a; 惠普HP Designjet 500 PCL3GUI 驱动 For Win XP/Vista/Win 7/Win 8 32位 版本&#xff1a;7.10 发布日期&#xff1a;14 11 2012 文件大小&#xff1a;5.02 MB 操作系统&#xff1a;Windows XP / Windows 2003 / Windows Vista / Windows 2008 / Windows …

华为OD机试真题 JavaScript 实现【最多提取子串数目】【2023Q1 100分】

一、题目描述 给定由[a-z] 26 个英文小写字母组成的字符串 A和 B&#xff0c;其中A中可能存在重复字母&#xff0c;B 中不会存在重复字母&#xff0c;现从字符串 A 中按规则挑选一些字母&#xff0c;可以组成字符串 B。 挑选规则如下: 同一个位置的字母只能被挑选一次&#…

usb万能驱动win7_IT知识大全:驱动程序详解!

对于计算机用户&#xff0c;基本都听过或者安装过驱动程序&#xff0c;每当我们将新硬件接入电脑主板上时&#xff0c;需要安装对应的驱动程序才能让硬件正常工作。 有不少用户在安装驱动程序时出现驱动不匹配&#xff0c;或者是在硬件使用一段时间后&#xff0c;驱动程序出现故…