[flutter] StreamBuilder를 사용하여 TextField의 값을 업데이트하는 방법은 무엇입니까?

나는이 textfield와 내가 사용하고 sqflite내 응용 프로그램에서 데이터베이스를. sqflite에 할당 해야하는 값 이 있습니다.textfield

여기 내 textfield코드가 있습니다

 StreamBuilder<String>(
    stream: patientHealthFormBloc.doctorName,
    builder: (context, snapshot) {
      return TextFormField(
        initialValue: patientHealthFormBloc.doctorNameValue,
        onChanged: (value) {
          patientHealthFormBloc.doctorNameChanged(value);
        },
        ...

이제 initstate내 수업 의 방법으로 데이터베이스에서 값을 가져오고 있습니다. 비동기 작업이므로 시간이 걸립니다.

내 블록 클래스에는 다음과 같은 코드가 있습니다

Function(String) get doctorNameChanged => _doctorName.sink.add;

데이터베이스에서 값을 수신하자마자 다음을 호출합니다.

doctorNameChanged("valuefromdatabase");

하지만 텍스트 필드에서 값을 볼 수 없습니다. 또한 내 데이터베이스에 값이 있습니다. 그것은 사용하지 않고 값을 업데이트하는 것이 가능 TextEditingControllersetState. 내 클래스가 너무 나는과 같은 방법을 사용하여 시도 위의 중 하나를 사용하여 복잡 chuncks와 방법, 많이 나누어으로 사람들을 피하려고 엄마 RadioButtonCheckBox그들은 제대로 업데이트 할 것 같다. _doctorName.stream.value데이터베이스 에 있는 값도 업데이트 되지만 textfield데이터는 표시되지 않습니다. 또한 색상 변경을 시도했지만 textfield거기에 문제가 없으며 입력 한 내용을 볼 수 있습니다.

https://github.com/PritishSawant/demo/tree/master/lib 앱의 작은 데모를 만들었습니다.

을 사용하는 대신 sqflite사용하고 shared preferences있지만 문제가 지속됩니다.



답변

OK 그래서 마침내 내 문제에 대한 해결책을 찾았습니다.

다음은 내 코드 입니다. 아래 예 SharedPreferences대신 방금 사용 sqflite했습니다.sqflite

class _MyHomePageState extends State<MyHomePage> {

  MyBloc myBloc = MyBloc();
  TextEditingController myController = TextEditingController();

  @override
  void dispose() {
    myBloc?.close();
    myController?.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    AppPreferences.setString("data", "this is my data");
    AppPreferences.getString("data").then((value){
      myBloc.dataChanged(value);
    });
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder(
          stream: myBloc.data,
           builder: (context,snapshot){

            debugPrint(snapshot.data);
            myController.value = myController.value.copyWith(text: myBloc.dataValue);

            return TextFormField(
              controller: myController,
              onChanged: (value){
                myBloc.dataChanged(value);
              },
            );
           },
        ),
      ),
    );
  }
}


답변

다음 접근법을 시도하십시오.

StreamBuilder<String>(
  stream: patientHealthFormBloc.doctorName,
  builder: (context, snapshot) {
    String doctorName = patientHealthFormBloc.doctorNameValue;
    if(snapshot.hasData){
      doctorName = snapshot.data/*(your name string from the stream)*/;
    } 
    return TextFormField(
      initialValue: doctorName,
      onChanged: (value) {
        patientHealthFormBloc.doctorNameChanged(value);
      },
    ...

도움이 더 필요하면 알려주십시오.


답변

내 의견에서 제안한 것은 다음과 같습니다.

TextEditingController _textEditingController = TextEditingController();

@override
void initState() {
  patientHealthFormBloc.doctorName.listen((snapshot){
    setState((){
      _textEditingController.text = snapshot;
    });
  });
  super.initState();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(
      children: <Widget>[
      TextFormField(
        controller: _textEditingController,
        onChanged: (value) {
          patientHealthFormBloc.doctorNameChanged(value);
        },
      ],
    ),
  );
}

TextEditingController 또는 setState를 사용하고 싶지 않은 이유를 이해하지 않고이 답변을 작성하고 싶지 않았습니다. 그러나 이것은 블록 패턴을 사용하는 동안 원하는 것을 달성해야합니다.


답변