how to edit value at the child widget

对着背影说爱祢 提交于 2021-02-11 13:01:39

问题


i try to edit the value of the child widget, i can do it with StatefulWidget parent but i want to do it with StatelessWidget parent and without using global value

    class Homepage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          FlatButton(child: Text('addFile'), onPressed: () {}),
          FlatButton(child: Text('deleteFile'), onPressed: () {})
        ],
      ),
      body: Child(),
    );
  }
}

class Child extends StatefulWidget {
  @override
  _ChildState createState() => _ChildState();
}

class _ChildState extends State<Child> {
  var hasFile = true;
  @override
  Widget build(BuildContext context) {
    return hasFile ? Text('has a file') : Text("no File");
  }
}

回答1:


You are thinking the wrong way. Child aka Text() should get its value from a model which is managed by the application or at least managed by the widget above. I would go with the provider package https://pub.dev/packages/provider and do this:

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


class MyState with ChangeNotifier {
  String _myText;

  MyState(this._myText);

  getMyText() => _myText;

  void changeText(String newText) {
    _myText = newText;
    notifyListeners();
  }
}

class Homepage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider(builder: (_) => MyState("initial Text")),
        ],
        child: Scaffold(
          appBar: AppBar(
            actions: <Widget>[
              FlatButton(
                  child: Text('addFile'),
                  onPressed: () {
                    Provider.of<MyState>(context).changeText("addFile");
                  }),
              FlatButton(
                  child: Text('deleteFile'),
                  onPressed: () {
                    Provider.of<MyState>(context).changeText("deleteFile");
                  })
            ],
          ),
          body: Child(),
        ));
  }
}

class Child extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    MyState myState = Provider.of<MyState>(context);
    return Text(myState.getMyText());
  }
}

This is coded without IDE support or even compiling and running. But it should get you to the right direction.




回答2:


You can use BLoC pattern to implement this kind of functionality,

Here is the BLoC class which will handle state of bool

import 'dart:async';

class Bloc {
  final _fileController = StreamController<bool>();

  changeState(bool val) {
    _fileController.sink.add(val);
  }

  get hasFile => _fileController.stream;

  dispose() {
    _fileController.close();
  }
}

final bloc = Bloc();

Then you can add stream builder in your Stateful Widget, in which you will provide stream of BLoC class. StreamBuilder updates it's UI according to Stream.

class Child extends StatefulWidget {
  @override
  _ChildState createState() => _ChildState();
}

class _ChildState extends State<Child> {
  var hasFile = true;

  @override
  void dispose() {
    bloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: bloc.hasFile,
      initialData: false,
      builder: (context, snapshot) {
        return snapshot.data ? Text('has a file') : Text("no File");
      },
    );
  }
}

At last you can access BLoC class with your stateless widget as follows

class Homepage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          FlatButton(
              child: Text('addFile'),
              onPressed: () {
                bloc.changeState(true);
              }),
          FlatButton(
              child: Text('deleteFile'),
              onPressed: () {
                bloc.changeState(false);
              })
        ],
      ),
      body: Child(),
    );
  }
}

Full example is as below

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Homepage(),
    );
  }
}

class Homepage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          FlatButton(
              child: Text('addFile'),
              onPressed: () {
                bloc.changeState(true);
              }),
          FlatButton(
              child: Text('deleteFile'),
              onPressed: () {
                bloc.changeState(false);
              })
        ],
      ),
      body: Child(),
    );
  }
}

class Child extends StatefulWidget {
  @override
  _ChildState createState() => _ChildState();
}

class _ChildState extends State<Child> {
  var hasFile = true;

  @override
  void dispose() {
    bloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: bloc.hasFile,
      initialData: false,
      builder: (context, snapshot) {
        return snapshot.data ? Text('has a file') : Text("no File");
      },
    );
  }
}

class Bloc {
  final _fileController = StreamController<bool>();

  changeState(bool val) {
    _fileController.sink.add(val);
  }

  get hasFile => _fileController.stream;

  dispose() {
    _fileController.close();
  }
}

final bloc = Bloc();


来源:https://stackoverflow.com/questions/57969370/how-to-edit-value-at-the-child-widget

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!