簡體   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