วิธีอัปเดตค่าสำหรับ TextField โดยใช้ StreamBuilder


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");

แต่ฉันไม่เห็นคุณค่าในฟิลด์ข้อความของฉัน นอกจากนี้ยังมีค่าอยู่ในฐานข้อมูลของฉัน มันเป็นไปได้ที่จะปรับปรุงค่าโดยไม่ต้องใช้หรือTextEditingController setStateฉัน ma พยายามที่จะหลีกเลี่ยงการเหล่านั้นเป็นชั้นเรียนของฉันจะแบ่งออกเป็นจำนวนมาก chuncks และวิธีการที่ซับซ้อนเกินไปที่จะใช้ใด ๆ ข้างต้นที่ผมได้ลองใช้วิธีการเดียวกันกับRadioButtonและCheckBoxและพวกเขาดูเหมือนจะอัปเดตอย่างถูกต้อง ค่าจะถูกอัพเดต _doctorName.stream.valueซึ่งมีอยู่ในฐานข้อมูล แต่textfieldไม่แสดงข้อมูลใด ๆ นอกจากนี้ฉันพยายามเปลี่ยนสีของtextfieldดังนั้นจึงไม่มีปัญหาเช่นเดียวกับที่ฉันสามารถดูสิ่งที่ฉันพิมพ์

ฉันได้ทำการสาธิตแอพเล็ก ๆhttps://github.com/PritishSawant/demo/tree/master/lib

แทนที่จะใช้sqfliteฉันกำลังใช้shared preferencesแต่ปัญหายังคงมีอยู่


ลองลบ "initialValue: patientHealthFormBloc.doctorNameValue" และเริ่มใน "initialData" จาก StreamBuilder
Stel

@Stel ขอบคุณ แต่ใช้งานไม่ได้
นัด

คุณสามารถใช้ TextEditingController (text

@ChinkySight ฉันใช้ Stream เพื่อหลีกเลี่ยง TextEditingController แอพมีความซับซ้อนและการใช้ TextEditingController นั้นไม่สามารถทำได้
Nudge

ในตัวอย่างของคุณคุณไม่ได้ใช้สแนปชอตเลย คุณคาดหวังว่าจะดึงข้อมูลใดมาใช้ใน TextFormField ของคุณ ทำไมคุณไม่สามารถใช้ TextEditingController ได้?
João Soares

คำตอบ:


4

ตกลงดังนั้นในที่สุดฉันก็พบวิธีแก้ปัญหาของฉัน

ต่อไปนี้เป็นรหัสของฉันฉันเพิ่งใช้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 ดังนั้นจึงอาจพิจารณาออกแบบวิศวกรรมให้คุณ
Nudge

หากคุณสามารถอธิบายได้ว่าเหตุใดคุณจึงต้องการสตรีม (อัปเดต) ค่าของ TextFieldForm ในเวลาเดียวกันที่ผู้ใช้อาจใช้งานอยู่ฉันอาจช่วยคุณได้ การซิงค์กับ SQFlite และ Firestore ไม่มีส่วนเกี่ยวข้องกับการอ้างสิทธิ์ของฉันว่าโซลูชันที่คุณนำเสนอนั้นได้รับการออกแบบทางวิศวกรรมมากเกินไป
João Soares

@ JoãoSoaresโปรดอ่านคำถามอีกครั้ง
เขี่ย

ฉันได้อ่านคำถามหลายครั้งแล้วและได้เห็นรหัสที่คุณแชร์บน GitHub คำอธิบายของคุณพูดถึงสิ่งที่คุณต้องการจะทำและวิธีที่คุณต้องการเขียนรหัส ไม่ได้อธิบายว่าทำไมคุณจึงต้องการให้ 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

เมื่อฉันพิมพ์ข้อความฉันได้รับข้อความที่พิมพ์ ในช่วงเริ่มต้นเมื่อฉันดึงข้อมูลจาก db มันจะทำการพิมพ์ค่า db StreamBuilder ทำงานได้ดีและการปรับปรุงค่าเมื่อฉันพิมพ์ด้วยตนเอง แต่จะไม่อัปเดตเมื่อดึงมาจากฐานข้อมูล
เขยิบ

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 แต่สิ่งนี้ควรบรรลุสิ่งที่คุณต้องการในขณะที่ใช้รูปแบบ Bloc


ฉันมีความคิดนี้ในตอนแรก แต่เนื่องจากคำถามที่ยกมาและ @Nudge ยืนยันว่าไม่ได้ใช้TextEditControllerดังนั้นฉันจึงคัดลอกไอเดียนั้น มันยอดเยี่ยมที่เพียงใช้ตัวควบคุมโซลูชันจะง่ายและเล็กในการทำงานอย่างถูกต้อง ผลงานยอดเยี่ยม
Harshvardhan Joshi

1
ขอบคุณฉันขอบคุณมัน น่าเสียดายที่ผู้ใช้ดูเหมือนยืนกรานที่จะยึดมั่นในความคิดของตนเองและไม่พยายามเขียนวิธีแก้ปัญหาที่เหมาะสมเพราะพวกเขาตัดสินใจที่จะไม่ให้การตอบสนองที่ถูกต้องหรือความโปรดปราน
João Soares

ตกลง. ไม่เป็นไรแล้ว
Harshvardhan Joshi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.