Поставщик флаттера: как мне прослушать изменение поля класса внутри поля класса? - PullRequest
0 голосов
/ 29 апреля 2020

Учитывая следующую структуру класса Дарт / Флаттер:

import 'package:flutter/material.dart';

class A with ChangeNotifier {
  B _element1;
  B _element2;

  B get element1 => _element1;
  B get element2 => _element2;

  set element1(B value) {
    _element1 = value;
    notifyListeners();
  }

  set element2(B value) {
    _element2 = value;
    notifyListeners();
  }
}

class B {
  String x;
  String y;
}

Я пытаюсь прослушать изменение A.element1.x, но проблема в том, что установщик класса B не может вызвать notifyListeners() класса A, поэтому либо я слушаю A и не замечаю изменений, либо слушаю B и теряю контекст для A.

Я использую пакет Provider в моем Flutter проект. Но я не уверен, если я неправильно понимаю концепцию пакета провайдера или ChangeListeners. В любом случае, я не могу найти элегантное решение.

Есть ли возможность перезаписать установщик класса B из класса A? Очевидно, я мог бы реализовать функцию для каждого поля element1 и element2 (x, y). Но я думаю, это не очень хороший стиль кода.

1 Ответ

1 голос
/ 30 апреля 2020

Вот пример того, как вы можете использовать функции обратного вызова. Без обратного вызова A не будет вызывать notifyListeners, а ваш Home виджет не будет перестроен. Вот короткое видео о том, что такое VoidCallback: https://www.youtube.com/watch?v=fWlPwj1Pp7U

Основная функция и простой Home просмотр:

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

import 'a.dart';

void main() {
  runApp(
    ChangeNotifierProvider<A>(
      create: (context) => A(),
      child: MaterialApp(
        home: Home(),
      ),
    )
  );
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<A>(
      builder: (context, model, child) {
        return Scaffold(
          body: Container(
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('${model.element1.x}'),
                  RaisedButton(
                    child: Text("Set x of element1."),
                    onPressed: () {
                      Provider.of<A>(context, listen: false).element1.setX = 'Set to new value';
                    },
                  ),
                ],
              ),
            ),
          )
        );
      },
    );
  }
}

А затем класс A :

import 'package:flutter/material.dart';
import 'package:tryout/b.dart';

class A extends ChangeNotifier {
  B _element1 = B();
  B _element2 = B();

  B get element1 => _element1;
  B get element2 => _element2;

  A() {
    _element1.callback = () => notifyListeners();
    _element2.callback = () => notifyListeners();
  }

  set element1(B value) {
    _element1 = value;
    _element1.callback = () => notifyListeners();
    notifyListeners();
  }

  set element2(B value) {
    _element2 = value;
    _element2.callback = () => notifyListeners();
    notifyListeners();
  }
}

И класс B:

import 'package:flutter/cupertino.dart';

class B {
  String x = "";
  String y = "";
  VoidCallback callback;

  B({
    this.callback
  });

  set setX(String newValueX) {
    x = newValueX;
    if(callback != null) callback();
  }

  void setY(String newValueY) {
    y = newValueY;
    if(callback != null) callback();
  }
}
...