繁体   English   中英

Flutter 使用在构建方法之外的未来构建器中创建的变量,

[英]Flutter use variable created inside Future builder outside of the build method,

我有一个未来的构建器女巫我用来获取数据,我需要使用我从 api 获得的文本编辑 controller 必须在构建之外定义,我需要提供文本编辑 Z594C103F2C6E04C3CD8AB0 的初始值,9031初始值我需要输入 data3.firstName 和 data3.lastName,现在初始值是硬编码的。

Future<Response> fetchAccountData() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String? authorization = prefs.getString('authorization');
  var url = 'https://dev.api.wurk.skyver.co/api/v1/employees/account';

  response1 = await http.get(
    Uri.parse(url),
    headers: <String, String>{
      'authorization': authorization ?? basicAuth.toString()
    },
  );

  return response1;
}

factory AccountData.fromJson(Map<String, dynamic> json) {
    return AccountData(
        firstName: json['firstName'],
        lastName: json['lastName'],
        phoneNumber: json['phoneNumber']);
  }
}

Future<void> putAccountData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? authorization = prefs.getString('authorization');
    var url = 'https://dev.api.wurk.skyver.co/api/v1/employees/account';
    Map payload = {
      "firstName": editedFirstName.text,
      "lastName": editedLastName.text,
    };
    try {
      final response = await http.put(Uri.parse(url),
          headers: <String, String>{
            'authorization': authorization ?? basicAuth.toString(),
            "Content-Type": "application/json"
          },
          body: jsonEncode(payload));
    } catch (er) {}
  }

TextEditingController editedFirstName =
  TextEditingController(text: 'firstName'); << needs to be data3.firstName
  TextEditingController editedLastName =
  TextEditingController(text: 'lastName');<< needs to be data3.lastName

return SafeArea(
      child: WillPopScope(
        onWillPop: () async {
          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => const ProfileScreen(),
            ),
          );
          return shouldPop;
        },

body: FutureBuilder<Response>(
                  future: futureData,
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      AccountData data3 = AccountData.fromJson( << data3 has data3.firstName, and 
                                                                                   data3.lastName
                        json.decode(snapshot.data!.body),
                      );

您可以像这样使用后期初始化:

late TextEditingController editedFirstName;
late TextEditingController editedLastName;

return SafeArea(
   child: WillPopScope(
      onWillPop: () async {
         Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => const ProfileScreen(),
            ),
         );
         return shouldPop;
      },

body: FutureBuilder<Response>(
         future: futureData,
         builder: (context, snapshot) {
            if (snapshot.hasData) {
               AccountData data3 = AccountData.fromJson( << data3 has data3.firstName, and 
                                                                                   data3.lastName
                json.decode(snapshot.data!.body),
               );
               editedFirstName = TextEditingController(text: data3.firstname)
               editedLastName = TextEditingController(text: data3.lastname)

我不完全理解拥有全局 TextController 的原因(而且我认为这也不是一个好主意),但使用 Riverpod 它看起来像这样:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class AccountData {
  final String firstName;
  final String lastName;
  final String phoneNumber;
  
  AccountData({
    required this.firstName,
    required this.lastName,
    required this.phoneNumber,
  });
  
  factory AccountData.fromJson(Map<String, dynamic> json) {
    return AccountData(
      firstName: json['firstName'],
      lastName: json['lastName'],
      phoneNumber: json['phoneNumber'],
    );
  }
}

Future<Map<String, dynamic>> fetchAccountData() async {
  final response = {
    'firstName': 'Name',
    'lastName': 'LastName',
    'phoneNumber': '98786758690',
  };
  return Future.delayed(const Duration(seconds: 3), () => response);
}

final futureData = FutureProvider<AccountData>((_) async {
  final data = await fetchAccountData();
  return AccountData.fromJson(data);
});
  
final firstNameController = ChangeNotifierProvider<TextEditingController>((ref) {
  final controller = TextEditingController();
  ref.listen<AsyncValue<AccountData>>(futureData, (_, curr) {
    curr.whenOrNull(
      data: (d) => controller.text = d.firstName,
    );
  });
  
  return controller;
});

final lastNameController = ChangeNotifierProvider<TextEditingController>((ref) {
  final controller = TextEditingController();
  ref.listen<AsyncValue<AccountData>>(futureData, (_, curr) {
    curr.whenOrNull(
      data: (d) => controller.text = d.lastName,
    );
  });
  
  return controller;
});

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp();
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends ConsumerWidget {
  
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final firstController = ref.watch(firstNameController.notifier);
    final lastcontroller = ref.watch(lastNameController.notifier);
    return ref.watch(futureData).when(
      loading: () => const CircularProgressIndicator(),
      error: (e, _) => TextButton(
        child: Text('$e'),
        onPressed: () => ref.refresh(futureData),
      ),
      data: (_) {
        return Column(
          children: [
            TextField(
              controller: firstController,
            ),
            TextField(
              controller: lastcontroller,
            ),
          ]
        );
      }
    );
  }
}

现在跟随Hazar Belge使用后期初始化程序是一个好主意,如果没有 state 管理,这个想法将简单地使用 FutureBuilder,然后将数据传递给 StatefulWidget,后者使用该数据初始化 TextEditingControllers,然后再次使用 didUpdateWidget,所有这些都没有取决于外部 package (您的应用程序越大,您将需要使用更多包来帮助您快速开发,但我建议您尝试使用基本知识来掌握您可以使用框架做的所有事情)

暂无
暂无

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

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