Verileri Durum Bilgili Bir Pencere Öğesine Aktarma


115

Verileri oluştururken durum bilgisi olan bir parçacığa geçirmenin önerilen yolunun ne olduğunu merak ediyorum.

Gördüğüm iki stil:

class ServerInfo extends StatefulWidget {

  Server _server;

  ServerInfo(Server server) {
    this._server = server;
  }

  @override
    State<StatefulWidget> createState() => new _ServerInfoState(_server);
}

class _ServerInfoState extends State<ServerInfo> {
  Server _server;

  _ServerInfoState(Server server) {
    this._server = server;
  }
}

Bu yöntem hem bir değeri tutan ServerInfove _ServerInfoStatebiraz savurgan bir tavır sergileyen.

Diğer yöntem kullanmaktır widget._server:

class ServerInfo extends StatefulWidget {

  Server _server;

  ServerInfo(Server server) {
    this._server = server;
  }

  @override
    State<StatefulWidget> createState() => new _ServerInfoState();
}

class _ServerInfoState extends State<ServerInfo> {
  @override
    Widget build(BuildContext context) {
      widget._server = "10"; // Do something we the server value
      return null;
    }
}

Durum artık içinde _ServerInfoSatedeğil, widget'ta saklandığı için bu biraz geriye doğru görünüyor .

Bunun için bir en iyi uygulama var mı?


3
Yapıcı indirgenebilirServerInfo(this._server);
Günter Zöchbauer

Bu soru daha önce sorulmuştu: stackoverflow.com/questions/50428708/…
Blasanka


Bu cevap, bundan bir ay önce eklenir: stackoverflow.com/questions/50428708/…
Blasanka

Yanıtlar:


233

Yapıcısını Statekullanarak parametreleri geçirmeyin . Bunlara yalnızca kullanarak erişmelisiniz this.widget.myField.

Yalnızca kurucuyu düzenlemek çok fazla manuel çalışma gerektirmez; hiçbir şey getirmez. Alanlarını çoğaltmak için bir neden yok Widget.

DÜZENLE :

İşte bir örnek:

class ServerIpText extends StatefulWidget {
  final String serverIP;

  const ServerIpText ({ Key key, this.serverIP }): super(key: key);

  @override
  _ServerIpTextState createState() => _ServerIpTextState();
}

class _ServerIpTextState extends State<ServerIpText> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.serverIP);
  }
}

class AnotherClass extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ServerIpText(serverIP: "127.0.0.1")
    );
  }
}

23
Başka bir yorum, yapıcı aracılığıyla bir State nesnesine ilettiğiniz hiçbir şey asla güncellenmeyecektir!
Jonah Williams

4
Ve buradayım ve yorumu anlamıyorum. "Yapıcısını kullanarak parametreleri State'e iletmeyin". Peki parametreleri devlete nasıl aktarırım?
KhoPhi

6
@Rexford alanını kullanarak Statetüm özelliklerine zaten erişim olarak . Statefulwidget
Rémi Rousselet

4
@ RémiRousselet Bir metin alanını önceden doldurmak için foo kullanmak ve yine de kullanıcının onu düzenlemesine izin vermek istersem ne olur? Ayrıca eyalete başka bir foo özelliği eklemeli miyim?
Said Saifi

1
@ user6638204 Durumda başka bir foo özelliği oluşturabilir ve void initState()başlangıç ​​değerini ayarlamak için durumu geçersiz kılabilirsiniz . Örnek olarak bu dişli seçeneğini C kontrol edin .
Joseph Cheng

31

En iyi yol , yapıcısını kullanarak parametreleri State sınıfına aktarmamaktır. State sınıfında kullanarak kolayca erişebilirsiniz widget.myField.

Örneğin

class UserData extends StatefulWidget {
  final String clientName;
  final int clientID;
  const UserData(this.clientName,this.clientID);

  @override
  UserDataState createState() => UserDataState();
}

class UserDataState extends State<UserData> {
  @override
  Widget build(BuildContext context) {
    // Here you direct access using widget
    return Text(widget.clientName); 
  }
}

Gezinme ekranında verilerinizi iletin:

 Navigator.of(context).push(MaterialPageRoute(builder: (context) => UserData("WonderClientName",132)));

8

@ RémiRousselet'in yanıtlayıcısına ve @ user6638204'ün sorusuna dayanan başka bir cevap, başlangıç ​​değerlerini geçirmek ve daha sonra bunları durumda güncelleyebilmek istiyorsanız:

class MyStateful extends StatefulWidget {
  final String foo;

  const MyStateful({Key key, this.foo}): super(key: key);

  @override
  _MyStatefulState createState() => _MyStatefulState(foo: this.foo);
}

class _MyStatefulState extends State<MyStateful> {
  String foo;

  _MyStatefulState({this.foo});

  @override
  Widget build(BuildContext context) {
    return Text(foo);
  }
}

7
Foo = widget.foo gibi bir şey yapmak için doğrudan initState'i kullanabiliriz, yapıcıya geçiş gerekmez
Aqib

Buna argüman nasıl aktarılır?
Steev James

@SteevJames parçacığının MyStatefulisteğe bağlı bir adlandırılmış parametresi (özelliği) vardır, bu parçacığı arayarak oluşturabilirsinizMyStateful(foo: "my string",)
Kirill Karmazin

@Aqib initStateaşağıdaki senaryoda bir sorunu çözmez: örneğin, Statefull widget'ınızı boş parametrelerle oluşturdunuz ve verilerinizin yüklenmesini bekliyorsunuz. Veriler yüklendiğinde, Statefull widget'inizi yeni verilerle güncellemek istersiniz ve bu durumda MyStatefull (newData) 'yı initState()çağırdığınızda, çağrılmaz! Bu durumda didUpdateWidget(MyStatefull oldWidget)adı verilecek ve argüman verilerinizi karşılaştırmak gerekir oldWidget.getData()ile widget.datave aynı değilse - çağrı setState()widget'ı yeniden inşa etmek.
Kirill Karmazin

1
@ kirill-karmazin Durumsuz pencere öğesi çözümü hakkında daha fazla ayrıntı verebilir misiniz? onun yerine ne kullanırdın? Flutter ekibinden bir en iyi uygulama mı? Teşekkür ederim
camillo777

4

İlk değerleri geçirmek için (kurucuya hiçbir şey iletmeden)

class MyStateful extends StatefulWidget {
  final String foo;

  const MyStateful({Key key, this.foo}): super(key: key);

  @override
  _MyStatefulState createState() => _MyStatefulState();
}

class _MyStatefulState extends State<MyStateful> {
  @override
  void initState(){
    super.initState();
    // you can use this.widget.foo here
  }

  @override
  Widget build(BuildContext context) {
    return Text(foo);
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.