我有一个颤动项目,我正在努力我不能把整个代码导致它超过500行代码所以我会尝试问我的问题就像我使用imp一样简单.代码部分.
我有一个有状态的小部件,并在扩展的类下面的有状态小部件中有一些函数 State<MusicPlayer>
文件 lib\main.dart
只需要一个简单的功能
class MyAppState extends State<MyApp>{
...
void printSample (){
print("Sample text");
}
...
Run Code Online (Sandbox Code Playgroud)
此函数位于主类中的有状态小部件内.
还有另一个文件 lib\MyApplication.dart
这个文件也有一个有状态的小部件,我可以做一些事情,这样我就可以在printSample()
这里调用函数..
class MyApplicationState extends State<MyApplication>{
...
@override
Widget build(BuildContext context) {
return new FlatButton(
child: new Text("Print Sample Text"),
onPressed :(){
// i want to cal the function here how is it possible to call the
// function
// printSample() from here??
}
);
}
...
}
Run Code Online (Sandbox Code Playgroud)
Mah*_*eja 42
您可以通过使用小部件的键来做到这一点
myWidget.dart
class MyWidget extends StatefulWidget {
const MyWidget ({Key key}) : super(key: key);
@override
State<StatefulWidget> createState()=> MyState();
}
class MyState extends State<MyWidget >{
Widget build(BuildContext context){ return ....}
void printSample (){
print("Sample text");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当使用 进myWidget声明GlobalKey作为全球关键
GlobalKey<MyState> _myKey = GlobalKey();
Run Code Online (Sandbox Code Playgroud)
并在创建小部件时传递它
MyWidget(
key : _myKey,
)
Run Code Online (Sandbox Code Playgroud)
通过这个键,你可以调用 state 内的任何公共方法
_myKey.currentState.printSample();
Run Code Online (Sandbox Code Playgroud)
bof*_*mer 41
要调用父项的函数,可以使用回调模式.在此示例中,将function(onColorSelected
)传递给子级.按下按钮时,孩子调用该功能:
import 'package:flutter/material.dart';
class Parent extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ParentState();
}
}
class ParentState extends State<Parent> {
Color selectedColor = Colors.grey;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
color: selectedColor,
height: 200.0,
),
ColorPicker(
onColorSelect: (Color color) {
setState(() {
selectedColor = color;
});
},
)
],
);
}
}
class ColorPicker extends StatelessWidget {
const ColorPicker({this.onColorSelect});
final ColorCallback onColorSelect;
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
RaisedButton(
child: Text('red'),
color: Colors.red,
onPressed: () {
onColorSelect(Colors.red);
},
),
RaisedButton(
child: Text('green'),
color: Colors.green,
onPressed: () {
onColorSelect(Colors.green);
},
),
RaisedButton(
child: Text('blue'),
color: Colors.blue,
onPressed: () {
onColorSelect(Colors.blue);
},
)
],
);
}
}
typedef ColorCallback = void Function(Color color);
Run Code Online (Sandbox Code Playgroud)
内部颤动小部件(如按钮或表单字段)使用完全相同的模式.如果您只想调用不带任何参数的函数,则可以使用该VoidCallback
类型来定义自己的回调类型.
如果要通知较高的父级,可以在每个层次结构级别重复此模式:
class ColorPickerWrapper extends StatelessWidget {
const ColorPickerWrapper({this.onColorSelect});
final ColorCallback onColorSelect;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(20.0),
child: ColorPicker(onColorSelect: onColorSelect),
)
}
}
Run Code Online (Sandbox Code Playgroud)
在Flutter中不鼓励从父窗口小部件调用子窗口小部件的方法.相反,Flutter鼓励您将子状态作为构造函数参数传递下去.您只需调用setState
父窗口小部件来更新其子窗口,而不是调用子窗口的方法.
一种替代的方法是controller
在扑(类ScrollController
,AnimationController
...).它们也作为构造函数参数传递给子setState
节点,它们包含控制子节点状态而不调用父节点的方法.例:
scrollController.animateTo(200.0, duration: Duration(seconds: 1), curve: Curves.easeInOut);
Run Code Online (Sandbox Code Playgroud)
然后,孩子们需要听取这些更改以更新其内部状态.当然,您也可以实现自己的控制器类.如果您需要,我建议您查看Flutter的源代码,了解其工作原理.
期货和流是传递状态的另一种选择,也可以用来调用孩子的功能.
但我真的不推荐它.如果您需要调用子窗口小部件的方法,那就非常类似于您的应用程序架构存在缺陷.尝试将状态移动到共同的祖先!
mkf*_*mkf 16
如果你想调用 printSample() func 你可以使用:
class Myapp extends StatefulWidget{
...
MyappState myAppState=new MyappState();
@override
MyappState createState() => myAppState;
void printSample(){
myAppState.printSample();
}
}
class MyAppState extends State<MyApp>{
void printSample (){
print("Sample text");
}
}
...............
Myapp _myapp = new Myapp();
myapp.printSample();
...
Run Code Online (Sandbox Code Playgroud)
在使用回调和GlobalKey
\'s 对于简单的用例来说很好,但对于更复杂的设置,它们可能应该被视为反模式,因为它们挂钩到小部件类型并依赖于低级实现逻辑。
如果您发现自己添加了越来越多的回调/全局键,并且开始变得混乱,那么可能是时候切换到类似StreamController
+的东西了StreamSubscription
的东西了。通过这种方式,您可以将事件与特定的小部件类型解耦,并抽象出小部件间的通信逻辑。
在您的顶级小部件(应用程序级或页面级,具体取决于您的需要)中创建实例StreamController
,并确保在dispose()
方法中释放它:
class _TopLevelPageState extends State<TopLevelPage> {\n StreamController<MyCustomEventType> eventController = StreamController<MyCustomEventType>.broadcast();\n\n// ...\n @override\n void dispose() {\n eventController.close();\n super.dispose();\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n将eventController
实例作为构造函数参数传递到任何需要侦听事件和/或触发事件的子小部件中。
\n\n\n
MyCustomEventType
可以是一个枚举(如果您不需要传递额外的数据),也可以是一个常规对象,其中包含您需要的任何字段,以防您需要在事件上设置额外的数据。
现在在任何一个小部件(包括父小部件,您在其中声明了StreamController
)中,您可以通过以下方式触发事件:
eventController.sink.add(MyCustomEventType.UserLoginIsComplete);\n
Run Code Online (Sandbox Code Playgroud)\n要在您的子窗口小部件(或父窗口小部件)中设置侦听器,请将以下代码放入initState()
:
\nclass _ChildWidgetState extends State<ChildWidget> {\n @override\n void initState() {\n super.initState();\n // NOTE: \'widget\' is the ootb reference to the `ChildWidget` instance. \n this.eventSubscription = widget.eventController.stream.asBroadcastStream().listen((event) {\n if (event == MyCustomEventType.UserLoginIsComplete) {\n print(\'handling LOGIN COMPLETE event \' + event.toString());\n } else {\n print(\'handling some other event \' + event.toString());\n }\n }\n\n @override\n void dispose() {\n this.parentSubscription.cancel();\n super.dispose();\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n\n请注意,如果您重写StreamController.done()那么您的侦听器将不会触发,因为
\ndone()
会替换您之前设置的任何侦听器。
注意:如果两个小部件之间有一对一的通信关系,那么您不需要广播事件风味 \xe2\x80\x94 在这种情况下,您可以创建不带 的控制器,.broadcast()
即使用StreamController<MyCustomEventType>()
和 来监听,而不是.stream.asBroadcastStream().listen()
可以使用.stream.listen()
。另请参阅https://api.dart.dev/stable/dart-async/Stream-class.html \n
有关概述此方法和其他方法的答案,请参阅Inter Widget communications
\n您可以尝试一下,它会从( ) 小部件调用Page2
( StatefulWidget
) 中定义的方法。Page1
StatefulWidget
class Page1 extends StatefulWidget {
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("Call page 2 method"),
onPressed: () => Page2().method(),
),
),
);
}
}
class Page2 extends StatefulWidget {
method() => createState().methodInPage2();
@override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
methodInPage2() => print("method in page 2");
@override
Widget build(BuildContext context) => Container();
}
Run Code Online (Sandbox Code Playgroud)
我通过反复试验找到了另一种解决方案,但它奏效了。
import 'main.dart' as main;
Run Code Online (Sandbox Code Playgroud)
然后将此行添加到onPressed下。
main.MyAppState().printSample();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
27923 次 |
最近记录: |