Flutter 颤振:当我热重新加载我的提供者时,创建新对象

Flutter 颤振:当我热重新加载我的提供者时,创建新对象,flutter,dart,Flutter,Dart,这是我的第一个问题,如果我犯了错误,我很抱歉。 关于我的问题,我发现了一些类似的问题,但没有一个能真正解决我的问题 所以我在我的项目中使用了Provider4.0.2,当我使用我的应用程序导航时,它可以正常工作,但是当我尝试热重新加载时,我的Provider会丢失状态,我的对象会重新开始 我就是这样实施的: main.dart void main() { Provider.debugCheckInvalidValueType = null; runApp( MultiProvid

这是我的第一个问题,如果我犯了错误,我很抱歉。 关于我的问题,我发现了一些类似的问题,但没有一个能真正解决我的问题

所以我在我的项目中使用了Provider4.0.2,当我使用我的应用程序导航时,它可以正常工作,但是当我尝试热重新加载时,我的Provider会丢失状态,我的对象会重新开始

我就是这样实施的:

main.dart

void main() {
  Provider.debugCheckInvalidValueType = null;
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider<ExpenseDAO>(create: (context) => ExpenseDAO()),
        ChangeNotifierProxyProvider<ExpenseDAO, ExpensesData>(
            update: (context, dao, expensesData) => ExpensesData(dao: dao)),
        ChangeNotifierProvider<User>(create: (context) => User()),
      ],
      child: MyApp(),
    ),
  );
}
class ExpensesData with ChangeNotifier {
  ExpensesData({@required this.dao}) {
    print('new object');
  }

  final List<Expense> _expenses = [];
  final ExpenseDAO dao;
  bool _isLoaded = false;

  bool get isLoaded => _isLoaded;

  UnmodifiableListView<Expense> get expenses => UnmodifiableListView(_expenses);

  saveExpense(Expense expense) async {
    await dao.insertExpense(expense);
    await loadList(expense.userId);
    notifyListeners();
  }

  loadList(String userId) async {
    _expenses.clear();
    _expenses.addAll(await dao.expenses(userId));
    _isLoaded = true;
  }
class ExpensesScreen extends StatefulWidget {
  static const String id = 'expense_screen';

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

class _ExpensesScreenState extends State<ExpensesScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kColorBackground,
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text(
          'Expenses',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Center(
              child: Consumer<ExpensesData>(
                builder: (context, expensesData, child) {

              return ListView.separated(
                  itemBuilder: (context, index) {
                    return Text(
                        'Tag = ${expensesData.expenses[index].category} '
                        '// Value = ${expensesData.expenses[index].value}');
                  },
                  separatorBuilder: (context, index) => Divider(),
                  itemCount: expensesData.expenses.length);
                },
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(
          Icons.add,
          size: 40,
        ),
        onPressed: () {
          Navigator.pushNamed(context, AddExpenseScreen.id);
        },
      ),
    );
  }
}
void main(){
Provider.debugCheckInvalidValueType=null;
runApp(
多供应商(
供应商:[
ChangeNotifierProvider(创建:(上下文)=>ExpenseDAO()),
ChangeNotifierProxyProvider(
更新:(context,dao,expensesData)=>expensesData(dao:dao)),
ChangeNotifierProvider(创建:(上下文)=>User()),
],
子项:MyApp(),
),
);
}
费用数据。dart

void main() {
  Provider.debugCheckInvalidValueType = null;
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider<ExpenseDAO>(create: (context) => ExpenseDAO()),
        ChangeNotifierProxyProvider<ExpenseDAO, ExpensesData>(
            update: (context, dao, expensesData) => ExpensesData(dao: dao)),
        ChangeNotifierProvider<User>(create: (context) => User()),
      ],
      child: MyApp(),
    ),
  );
}
class ExpensesData with ChangeNotifier {
  ExpensesData({@required this.dao}) {
    print('new object');
  }

  final List<Expense> _expenses = [];
  final ExpenseDAO dao;
  bool _isLoaded = false;

  bool get isLoaded => _isLoaded;

  UnmodifiableListView<Expense> get expenses => UnmodifiableListView(_expenses);

  saveExpense(Expense expense) async {
    await dao.insertExpense(expense);
    await loadList(expense.userId);
    notifyListeners();
  }

  loadList(String userId) async {
    _expenses.clear();
    _expenses.addAll(await dao.expenses(userId));
    _isLoaded = true;
  }
class ExpensesScreen extends StatefulWidget {
  static const String id = 'expense_screen';

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

class _ExpensesScreenState extends State<ExpensesScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kColorBackground,
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text(
          'Expenses',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Center(
              child: Consumer<ExpensesData>(
                builder: (context, expensesData, child) {

              return ListView.separated(
                  itemBuilder: (context, index) {
                    return Text(
                        'Tag = ${expensesData.expenses[index].category} '
                        '// Value = ${expensesData.expenses[index].value}');
                  },
                  separatorBuilder: (context, index) => Divider(),
                  itemCount: expensesData.expenses.length);
                },
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(
          Icons.add,
          size: 40,
        ),
        onPressed: () {
          Navigator.pushNamed(context, AddExpenseScreen.id);
        },
      ),
    );
  }
}
class ExpensesData与ChangeNotifier{
ExpensesData({@required this.dao}){
打印(“新对象”);
}
最终清单_费用=[];
最终费用;
bool_isLoaded=false;
bool get isLoaded=>\u isLoaded;
UnmodifiableListView获取费用=>UnmodifiableListView(\u费用);
saveExpense(费用支出)异步{
等待道。插入费用(费用);
等待加载列表(expense.userId);
notifyListeners();
}
加载列表(字符串用户ID)异步{
_费用;
_expenses.addAll(等待dao.expenses(userId));
_isLoaded=true;
}
这就是我的问题所在。当热重新加载我得到一个新对象时,我可以通过在控制台中热重新加载时打印“new object”来看到这一点,之后费用列表为空,我的属性“isLoaded”返回为false

费用\u屏幕省道

void main() {
  Provider.debugCheckInvalidValueType = null;
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider<ExpenseDAO>(create: (context) => ExpenseDAO()),
        ChangeNotifierProxyProvider<ExpenseDAO, ExpensesData>(
            update: (context, dao, expensesData) => ExpensesData(dao: dao)),
        ChangeNotifierProvider<User>(create: (context) => User()),
      ],
      child: MyApp(),
    ),
  );
}
class ExpensesData with ChangeNotifier {
  ExpensesData({@required this.dao}) {
    print('new object');
  }

  final List<Expense> _expenses = [];
  final ExpenseDAO dao;
  bool _isLoaded = false;

  bool get isLoaded => _isLoaded;

  UnmodifiableListView<Expense> get expenses => UnmodifiableListView(_expenses);

  saveExpense(Expense expense) async {
    await dao.insertExpense(expense);
    await loadList(expense.userId);
    notifyListeners();
  }

  loadList(String userId) async {
    _expenses.clear();
    _expenses.addAll(await dao.expenses(userId));
    _isLoaded = true;
  }
class ExpensesScreen extends StatefulWidget {
  static const String id = 'expense_screen';

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

class _ExpensesScreenState extends State<ExpensesScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kColorBackground,
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text(
          'Expenses',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Center(
              child: Consumer<ExpensesData>(
                builder: (context, expensesData, child) {

              return ListView.separated(
                  itemBuilder: (context, index) {
                    return Text(
                        'Tag = ${expensesData.expenses[index].category} '
                        '// Value = ${expensesData.expenses[index].value}');
                  },
                  separatorBuilder: (context, index) => Divider(),
                  itemCount: expensesData.expenses.length);
                },
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(
          Icons.add,
          size: 40,
        ),
        onPressed: () {
          Navigator.pushNamed(context, AddExpenseScreen.id);
        },
      ),
    );
  }
}
class ExpenseScreen扩展StatefulWidget{
静态常量字符串id='expense_screen';
@凌驾
_ExpensesScreenState createState()=>\u ExpensesScreenState();
}
类别费用筛选状态扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
背景颜色:kColorBackground,
appBar:appBar(
背景颜色:Colors.white,
标题:正文(
"开支",,
样式:TextStyle(颜色:Colors.black),
),
),
主体:容器(
子:列(
儿童:[
居中(
儿童:消费者(
生成器:(上下文、费用数据、子项){
返回ListView.separated(
itemBuilder:(上下文,索引){
返回文本(
'Tag=${expensesData.expenses[index].category}'
'//Value=${expensesData.expenses[index.Value}');
},
separatorBuilder:(上下文,索引)=>Divider(),
项目计数:费用数据、费用、长度);
},
),
),
],
),
),
浮动操作按钮:浮动操作按钮(
子:图标(
Icons.add,
尺码:40,
),
已按下:(){
pushNamed(上下文,AddExpenseScreen.id);
},
),
);
}
}
你们能帮我吗?
我真的认为这是我的代码中的一个问题,但我不知道它是什么。

阅读
ChangeNotifierProxyProvider
,它明确地说:

不要直接在更新中创建ChangeNotifier。
当使用的某个值更新时,这将导致您的状态丢失
您在以下方面违反了:

update:(context,dao,expensesData)=>expensesData(dao:dao)),
您应该将新的
dao
对象注入先前创建的
ExpensesData
对象,如(make
dao
不再是
final
):

update:(context,dao,expensesData)=>expensesData.dao=dao),

update:(context,dao,expensesData)=>expensesData.update(dao)),

这取决于您特定的代码和品味。

很难理解您的问题是什么,特别是那些代码,请尝试用一个较小的示例重现它,并更好地解释不应该发生的事情。@mFeinstein下次在您回答关于我解决问题的文档后,我将尝试提出一个更好的问题。@mFeinsteinem,非常感谢!!天哪,我已经阅读了文档,没有发现我犯了什么错误,非常感谢!再次阅读您的答案和文档后,我发现我没有创建提供者,而是直接在更新中创建的!!再次感谢!!