dart 如何在使用块框架时为文本字段给予默认值

yh2wf1be  于 2022-12-28  发布在  其他
关注(0)|答案(3)|浏览(129)

我已经写了一些简单的flutter应用程序,它们使用有状态的widget/ forms / textformfields来输入和管理数据。现在我正在尝试理解如何使用BLoC和streambuilder来做类似的工作。但是我不知道如何为我的字段设置初始值。
我试着创建了一个我能想到的最简单的例子,一个使用块的小应用程序,它只接受一个输入到TextField中的名称,并将其返回到下一行。

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bloc Example',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage();

  String initialData = 'Fred';

  @override
  Widget build(BuildContext context) {

    TextEditingController _controller = new TextEditingController();

    return Scaffold(
      appBar: AppBar(title: Text('Bloc Example')),
      body: Center(
        child: Column(
          children: <Widget>[
          StreamBuilder(
            initialData: initialData,
            stream: bloc.nameStream,
              builder: (context, snapshot) {
                if ( snapshot.connectionState == ConnectionState.waiting)
                  _controller.text = snapshot.data;
                return TextField(
                  controller: _controller,
                  onChanged: bloc.nameChangedStream,
                  decoration: InputDecoration(labelText: 'Enter name' ),
                );
              }
            ),
            StreamBuilder(
              initialData: initialData,
              stream: bloc.nameStream, //
              builder: (context, snapshot) {
                return Text('Name is ${snapshot.hasData ? snapshot.data : 'unknown'}');
              }
            ),
          ],
        ),
      ),
    );
  }
}

class Bloc
{
  final nameStreamController = BehaviorSubject<String>();
  Stream<String> get nameStream => nameStreamController.stream;
  Function(String) get nameChangedStream => nameStreamController.sink.add ;
}

final Bloc bloc = new Bloc();

我不知道如何给我的名字字段指定一个初始值。
我必须承认,从一个老式的编程背景,它花了我一段时间让我的思想进入React式编程-但向前和向上!
编辑-感谢给出的评论-更新代码使用TextEditingController和StreamBuilder initialData的组合,似乎工作正常。如果有更好的解决方案,很高兴接受进一步的评论:)

yruzcnhs

yruzcnhs1#

通过执行此操作,您可以为behaviorSubject提供一个将用作其初始值的种子值。

final nameStreamController = BehaviorSubject<String>.seeded('InitialName');

对于旧版本的rxDart,请使用

final nameStreamController = BehaviorSubject<String>(seedValue:'InitialName');
hgqdbh6s

hgqdbh6s2#

在不知道要如何处理name字段的情况下,您可以选择以下几种方法。
您可以为InputDecorationInputDecoration(hintText: 'name'))提供一个hintText
您可以在StreamBuilder上设置初始值:

StreamBuilder(
  stream: bloc.nameStream,
  initialData: 'Initial Name',
    builder: (context, snapshot) {
      return TextField(
        onChanged: bloc.nameChangedStream,
        decoration: InputDecoration(labelText: 'Enter name' ),
      );
    }
  ),

但是,这不会在流中持久化该值,因此如果用户不更改文本字段,“Initial Name”将不会出现在nameStreamController的流中。
正如@nonybrighto提到的,可以用初始值作为nameStreamController的种子。
如果您不能使用种子值,您还可以在块的init期间向流添加初始值:

class Bloc {
  final nameStreamController = BehaviorSubject<String>();
  Stream<String> get nameStream => nameStreamController.stream;
  Function(String) get nameChangedStream => nameStreamController.sink.add;

  Bloc() {
    String initialValue = _getInitialValue();
    nameStreamController.add(initialValue);
  }
}

下面是一个更完整的真实示例:我们找到了这个认证和登录BLoC示例,其中我们遵循了下面列出的许多内容:Didier Boelens BLOC示例。它向您展示了如何使用BLoC、React式编程和流来设置注册表单和授权。

pkmbmrz7

pkmbmrz73#

我找到了通过使用RxDart flutter 3.0来实现这一点的解决方案
首先,
1.从缓存状态获取初始文本。(存储在共享首选项或其他地方)。
1.声明TextEditingController以存储该文本。
1.调用该方法,该方法从initState方法返回初始文本。
对于StreamBuilder
1.使用StreamBuilder Package 您的TextField
1.在stream的StreamBuilder中,使用您要侦听的流。
1.在StreamBuilderbuilder方法内部,使用条件语句检查snapShot和textEditingController的条件,并相互交换。
下面是我的示例代码,我使用SharedPreference来存储数据。
从存储器中检索该代码。

final TextEditingController _cacheUserIdCtrl = TextEditingController();

  @override
  void initState() {
    getCacheUserId();
    super.initState();
  }

  void getCacheUserId() {
    SharedPref.retriveData(key: SharedPref.userId).then(
      (value) {
        _cacheUserIdCtrl.text = value!;
      },
    );
  }

这部分是用Streambuilder设置文本字段,设置初始文本,用户可以任意编辑。

Widget userIdField({required LoginBloc loginBloc}) {
    return StreamBuilder(
      stream: loginBloc.userIdStream,
      builder: (context, snapShot) {
        if (snapShot.hasData) {
          _cacheUserIdCtrl.text = snapShot.data!;
        } else {
          loginBloc.fillUserId(_cacheUserIdCtrl.text);
        }
        return TextFormField(
          onChanged: (value){
            TextSelection previousSelection = _cacheUserIdCtrl.selection;
            _cacheUserIdCtrl.selection = previousSelection;
            loginBloc.fillUserId;
          },
          keyboardType: TextInputType.number,
          controller: _cacheUserIdCtrl,
          maxLength: 8,
          textInputAction: TextInputAction.next,
          onSaved: (value) {
            userId = value!;
          },
          decoration: textFieldInputDecoration(
            hintText: 'Enter user id',
          ).copyWith(
            prefixIcon: const Icon(Icons.person),
            counterText: "",
          ),
        );
      },
    );
  }

对于集团的部分,我想你会自己做。那是所有人的。会起作用的。

相关问题