繁体   English   中英

在自定义小部件中调用方法

[英]Call a method inside custom widget

我创建了一个自定义小部件。 它包括带有后缀 IconButton 的只读 TextFormField、API、警报对话框和回调 function 小部件可以处于 2 种状态,设置或重置。

通过 TextFormField 上的 IconButton 将小部件置于设置状态,这将执行 API 调用,返回的数据显示在 TextFormField 上。
根据某些应用程序要求,从父屏幕重置小部件。

我已经在我的各种活动(屏幕)中导入并使用了这个自定义小部件。 他们在我的屏幕上我希望清除我的自定义小部件,并且我已经创建了 clear 方法。

我想知道我将把这个clearWidget方法称为谁。

如果需要,我可以clearWidget方法到class GetTimeWidget extends StatefulWidget

enum TimeWidgetEvent { Start, Stop }

class GetTimeWidget extends StatefulWidget {
  Ref<String> time;
  final TimeWidgetEvent mode;
  final String label;
  const GetTimeWidget({
    required this.time,
    required this.mode,
    required this.label,
    Key? key,
  }) : super(key: key);

  @override
  State<GetTimeWidget> createState() => _GetTimeWidgetState();
}

class _GetTimeWidgetState extends State<GetTimeWidget> {
final TextEditingController controller;
  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: controller,
      readOnly: true,
      //initialValue: ,
      decoration: InputDecoration(
        label: Text(widget.label),
        hintText: 'Please Get ${widget.label} from sever',
        suffixIcon: TextButton.icon(
          onPressed: () {
            //Execute API to get time
          },
          icon: (widget.mode == TimeWidgetEvent.Start)
              ? const Icon(Icons.play_circle)
              : const Icon(Icons.stop_circle),
          label: (widget.mode == TimeWidgetEvent.Start)
              ? const Text('Start')
              : const Text('Stop'),
        ),
        border: const OutlineInputBorder(),
      ),
      validator: (value) {
        if (value == null || value.isEmpty) {
          return 'Please Get ${widget.label} from server'; //Validation error
        }
        return null; //Validation Success
      },
    );
  }
  
  void clearWidget()
  {
    controller.clear();
    //Execute API
  }
}

我认为你不能。 因为 state class 是私有的,并且 class (_GetTimeWidgetState) 中的每个方法都不能从外部调用。 如果我正确理解你想要做什么,就是从这个小部件外部更改 _GetTimeWidgetState 的内部 state。

我认为你不能。 My suggest is to use one of the state managers that you can find for flutter, like Riverpod (my choice), or Cubit, Get/Getx, etc... In that manner you can read/change the internal state using the global state由 state 管理器管理。

例如,使用 Riverpod,您可以定义一个处理数据的 StateClass:

final myProvider = StateNotifierProvider<MyStateNotifier, MyState>((ref) {
    return MyStateNotifier("someInitialDataInfo");
 });

class MyStateNotifier extends StateNotifier<MyState> {
      MyStateNotifier("someInitialDataInfo") : super( MyState("someInitialDataInfo"));
    void clear(String someDataInfo)  { state = MyState( someDataInfo) ;}
}

@immutable
class MyState {
 ..... }

然后在您的 ComsumerState 中(在 Riverpod 中您应该使用 ConsumerStatefulWidget 和 ConsumerState),您可以在此处查看通知程序:

class _GetTimeWidgetState extends ConsumerState<GetTimeWidget> {
   final TextEditingController controller;

@override
  Widget build(BuildContext context, WidgetRef ref) {
   final myState = ref.watch(myProvider );
   if ( myState.someDataInfo == 'Clicked Reset!!!!' ) {
        controller.clear();
   }
   return TextFormField( .... );
 }
 .... } ...}

现在,观察当通知程序 class 内的 state 发生变化时,将调用构建方法。 因此,每次更改都会通知您一次。 在 StateNotifier class(用于扩展和定义 MyStateNotifier 类的 class)内部将执行以下匹配以将您的小部件置于脏状态:

state != oldState

这意味着每次您更改内部 state 字段时,它都会将您的小部件放入脏 state,因此它将被重新构建。 MyState class 被定义为@immutable ,因此每个 state 更改都不能通过以下方式完成:

 state.setMyField ( ' my value ' );

但将完成更改 state object 本身:

state =  MyState ( ... );

或使用其复制方法:

 state = state.copyWith( .... ) ;

通过这种方式,您可以避免一些副作用( state 应该始终是不可变的)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM