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


13

나는이 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있지만 문제가 지속됩니다.


제거 시도 "로 초기 : patientHealthFormBloc.doctorNameValue"을하고 StreamBuilder에서 "initialData"에서 시작
STEL

@Stel 감사하지만 작동합니까
너지

TextEditingController (text

@ChinkySight TextEditingController를 피하기 위해 Stream을 사용하고 있습니다. 이 앱은 복잡하고 TextEditingController을 사용하는 것은 가능하지 않다
너지

귀하의 예에서는 스냅 샷을 전혀 사용하지 않습니다. TextFormField에서 사용할 데이터는 무엇입니까? 왜 TextEditingController를 사용할 수 없습니까?
João Soares

답변:


4

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);
              },
            );
           },
        ),
      ),
    );
  }
}

이것은 매우 과도하게 설계된 솔루션입니다. 귀하의 특정 솔루션을 수정하기를 원치 않고 원래 정확히 달성하고자하는 것을 설명했으면합니다. 귀하의 질문에 댓글을 달았을 때 사용자가 적극적으로 사용하는 TextField를 실시간으로 업데이트하려고합니다. 이것은 매우 이상하고 나쁜 UX 일 것입니다.
João Soares

@ JoãoSoares 솔루션을 게시 할 수 있습니까? 현상금을 수여하고 귀하의 솔루션이 내 것보다 낫다면 기꺼이 받아들입니다. 이 이상 당신에게 설계 보일 수 있습니다 모든 사람이 이해할 수 있도록 그냥 쉽게 솔루션을 게시했지만 실제로 내 응용 프로그램은 sqflite뿐만 아니라 경우 FireStore와 동기화 필요
너지

사용자가 TextFieldForm의 값을 동시에 사용 (스트리밍)하려는 이유를 설명 할 수 있다면 도움이 될 수 있습니다. SQFlite 및 Firestore와 동기화해도 제시 한 솔루션이 과도하게 엔지니어링되었다는 주장에는 관여하지 않습니다.
João Soares

@ JoãoSoares 질문을 다시 읽으십시오.
너지

질문을 여러 번 읽었으며 GitHub에서 공유 한 코드를 보았습니다. 설명은 수행하려는 작업과 코드 작성 방법에 대해 설명합니다. Data Streaming 또는 해당 동작에 대한 전제로 TextFormField를 이러한 방식으로 채우려는 이유는 설명하지 않습니다.
João Soares

2

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

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);
      },
    ...

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


... 작동하지 않습니다
너지

스트림에서 새로운 이름을 받고 있습니까?
Harshvardhan Joshi

예 그러나 값이 업데이트지고 있지 않습니다
너지

당신은 같은 새로운 이름을 받고 builder: (context, snapshot)있습니까?
Harshvardhan Joshi

텍스트를 입력하면 입력 한 텍스트가 나타납니다. 그때가 이뤄졌다는 점이고 StreamBuilder 잘하고 내가 수동으로 입력 값 업데이트를 노력하고 있지만 데이터베이스에서 가져올 때이 업데이트되지 않는 DB를 인쇄 DB에서 가져 오는 초기 단계에서
너지

1

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

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를 사용하고 싶지 않은 이유를 이해하지 않고이 답변을 작성하고 싶지 않았습니다. 그러나 이것은 블록 패턴을 사용하는 동안 원하는 것을 달성해야합니다.


처음 에이 생각을했지만 질문이 인용되고 @Nudge가을 사용하지 말 것을 주장 TextEditController했기 때문에 그 아이디어를 폐기했습니다 . 컨트롤러를 사용해야 만 솔루션이 간단하고 작아 져서 정확하게 작동하는 것이 좋습니다. 잘 했어.
Harshvardhan Joshi

1
고마워요 불행히도 사용자는 자신의 생각을 고집하는 것처럼 보였고 올바른 해결책이나 현상금을 나타내지 않기로 결정한 적절한 해결책을 쓰려고 시도하지 않았습니다.
João Soares

오 알았어 그럼 신경 쓰지 마
Harshvardhan Joshi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.