[英]How To Get My Deeply Nested Data To Update Properly When Using Flutter_bloc 8.0.0+ And Equatable
簡介:我一直在研究這個問題。 該問題涉及使用 Bloc 8.0.0+ 范例更新深度嵌套數據的 state。 我正在使用一個 class ,其中包含深度嵌套的數據(在這個最小的可行代碼中:包含名稱和子項的“集合”旨在成為一個節目系列,並且該系列的子項旨在成為季節,並且很快...)。
嵌套結構是這樣的:
List<CollectionState>
|-- List<CollectionState>
| |-- List<CollectionState>
代碼的一個重要功能是,將一個子項添加到正確父項的子項列表中,以便在 ListView 中以父項層次結構的正確順序顯示其子項; 即集合有一個系列(8768),該系列有兩個季節(1817 和 7623),當按下一個季節時,一個情節被添加到其正確的父季節,而不是被添加到 ListView 的底部。 在這種情況下,按四次第 1817 季會在其下添加第 2175、2773、5420 和 8826 集,而不是添加到第 7623 季。
問題:據我了解,使用 BLoC 8.0.0+ 時的一個好習慣是使用 Equatable 擴展 CollectionState class。 我提供的以下代碼有效; 但是,它確實使用了這種最佳實踐。 我希望它這樣做,但我遇到了問題,我將很快解釋。 我在 collection_state.dart 的代碼中評論了:
// 1) where Equatable should be extended
當 CollectionState class 使用 Equatable 擴展時,我在 collection_bloc.dart 中出現問題的代碼中找到了(請注意,問題僅發生在通過擴展 CollectionState ZA2F2ED4F8EBC2CBB4C21A29DC4 來更改代碼時,而 EABDZ4 代碼不使用 EABDZ4) 我在代碼中評論了這條評論:
//TODO: Here is the problem. This code does not work properly when I extend the CollectionState class to Equatable.
令人驚訝的是,在 BLoC 8.0.0+ 中使用深度嵌套數據的在線信息很少。
我是 BLoC 8.0.0+ 的新手,甚至是 Equatable 的新手(到目前為止我一直使用 Provider),我不明白為什么我的代碼在擴展 Equatable 時沒有正確更新。 我想我遇到了一個不變性問題,因為使用AddInfo bloc 事件對 class 的更新被認為與 Equatable 不同。 我不知道如何更改我的代碼以使用 BLoC 深度嵌套數據的最佳實踐。
問題:
如何更改我的代碼以使用 Equatable 擴展 CollectionState class 並且仍然讓它正確更新我的 UI?
請記住,我對 Equatable 有一個粗略的了解,我想更多地了解問題的根本根源。 是否 bloc 事件方法沒有產生與 Equatable 足夠不同的 class ,所以它沒有更新或者這里發生了完全不同的事情?
發布規范.yaml
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.1.1
equatable: ^2.0.5
main.dart
import 'package:deeply_nested_objects/add_collection_logic.dart';
import 'package:deeply_nested_objects/bloc/collection_bloc.dart';
import 'package:deeply_nested_objects/bloc/collection_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CollectionBloc(),
child: const MaterialApp(
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<CollectionBloc, CollectionState>(
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Text('Deeply nested data and Bloc 8.0.0+'),
),
body: ListView.builder(
itemCount: state.getAllNodes(state).length,
itemBuilder: (context, index) {
var nodes = state.getAllNodes(state)[index];
return ListTile(
onTap: () => addToCollection(nodes.showType, index, context),
leading: Card(
child: Text(nodes.name),
),
);
},
),
);
},
);
}
}
add_collection_logic.dart
import 'dart:math';
import 'package:deeply_nested_objects/bloc/collection_bloc.dart';
import 'package:deeply_nested_objects/bloc/collection_event.dart';
import 'package:deeply_nested_objects/bloc/collection_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void addToCollection(ShowType showType, int index, BuildContext context) {
if (showType == ShowType.collection) {
BlocProvider.of<CollectionBloc>(context).add(AddInfo(
child: CollectionState(
name: "Series ${(1000 + Random().nextInt(9000))}",
showType: ShowType.series,
children: [],
),
index: index,
));
}
if (showType == ShowType.series) {
BlocProvider.of<CollectionBloc>(context).add(AddInfo(
child: CollectionState(
name: 'Season ${(1000 + Random().nextInt(9000))}',
showType: ShowType.season,
children: [],
),
index: index,
));
}
if (showType == ShowType.season) {
BlocProvider.of<CollectionBloc>(context).add(AddInfo(
child: CollectionState(
name: "Episode ${(1000 + Random().nextInt(9000))}",
showType: ShowType.episode,
children: [],
),
index: index,
));
}
}
collection_event.dart
import 'package:deeply_nested_objects/bloc/collection_state.dart';
import 'package:equatable/equatable.dart';
abstract class CollectionEvents extends Equatable {
@override
List<Object> get props => [];
}
class AddInfo extends CollectionEvents {
AddInfo({required this.index, required this.child});
final int index;
final CollectionState child;
}
collection_bloc.dart
import 'package:deeply_nested_objects/bloc/collection_event.dart';
import 'package:deeply_nested_objects/bloc/collection_state.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CollectionBloc extends Bloc<CollectionEvents, CollectionState> {
CollectionBloc() : super(CollectionState.initial()) {
on<AddInfo>((event, emit) {
if (event.child.showType == ShowType.series) {
emit(state.copyWith(children: [...state.children, event.child]));
}
if (event.child.showType == ShowType.season ||
event.child.showType == ShowType.episode) {
//TODO: Here is the problem. This code does not work properly when I extend the CollectionState class to Equatable.
// get the list of all nodes
List<CollectionState> list = state.getAllNodes(state);
// find the parent node while still in the list
CollectionState parent = list[event.index];
// add the child to the parent
parent.children.add(event.child);
// update the state
emit(state.copyWith(children: [...state.children]));
}
});
}
}
collection_state.dart
enum ShowType { collection, series, season, episode }
// 1) where should be Equatable
class CollectionState {
const CollectionState({
required this.name,
required this.children,
required this.showType,
});
final String name;
final List<CollectionState> children;
final ShowType showType;
factory CollectionState.initial() {
return const CollectionState(
name: "Collection",
showType: ShowType.collection,
children: [],
);
}
List<CollectionState> getAllNodes(CollectionState node) {
// empty list to store the result
List<CollectionState> result = [];
// add the current node
result.add(node);
// add the children too
for (CollectionState child in node.children) {
// composite design pattern seek and find
result.addAll(getAllNodes(child));
}
return result;
}
CollectionState copyWith({
String? name,
List<CollectionState>? children,
ShowType? showType,
}) {
return CollectionState(
name: name ?? this.name,
children: children ?? this.children,
showType: showType ?? this.showType,
);
}
}
您必須在要檢查相等性的 equatable 中分配屬性。
例子:
class SomeClass extends Equatable {
SomeClass({required this.index});
final int index;
@override
List<Object> get props => [];
}
如果我要檢查SomeClass(index: 10) == SomeClass(index: 9)
這將是正確的,因為我沒有說它應該在==
運算符上尋找什么屬性
如果我將代碼更新為
class SomeClass extends Equatable {
SomeClass({required this.index});
final int index;
@override
List<Object> get props => [index];
}
現在相同的檢查將是錯誤的,因為它正在查看索引屬性
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.