Skip to content

Commit c379fa7

Browse files
committed
fix(ObserverCore): improve the logic of handleListObserve and handleGridObserve
1 parent 458d837 commit c379fa7

File tree

2 files changed

+139
-4
lines changed

2 files changed

+139
-4
lines changed

lib/src/observer_core.dart

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class ObserverCore {
5252
var parentData = firstChild.parentData as SliverMultiBoxAdaptorParentData;
5353
var index = parentData.index ?? 0;
5454

55+
// Whether the first child being displayed is not found.
56+
bool isNotFound = false;
5557
// Find out the first child which is displaying
5658
var targetFirstChild = firstChild;
5759

@@ -63,15 +65,34 @@ class ObserverCore {
6365
)) {
6466
index = index + 1;
6567
var nextChild = _obj.childAfter(targetFirstChild);
66-
if (nextChild == null) break;
68+
if (nextChild == null) {
69+
isNotFound = true;
70+
break;
71+
}
6772

6873
if (nextChild is! RenderIndexedSemantics) {
6974
// It is separator
7075
nextChild = _obj.childAfter(nextChild);
7176
}
72-
if (nextChild == null) break;
77+
if (nextChild == null) {
78+
isNotFound = true;
79+
break;
80+
}
7381
targetFirstChild = nextChild;
7482
}
83+
84+
// The first child being displayed is not found, indicating that the
85+
// ScrollView is not visible.
86+
if (isNotFound) {
87+
return ListViewObserveModel(
88+
sliverList: _obj,
89+
viewport: viewport,
90+
visible: false,
91+
firstChild: null,
92+
displayingChildModelList: [],
93+
);
94+
}
95+
7596
if (targetFirstChild is! RenderIndexedSemantics) return null;
7697

7798
List<ListViewObserveDisplayingChildModel> displayingChildModelList = [
@@ -159,6 +180,8 @@ class ObserverCore {
159180
final rawScrollViewOffset = _obj.constraints.scrollOffset + overlap;
160181
var scrollViewOffset = rawScrollViewOffset + offset;
161182

183+
// Whether the first child being displayed is not found.
184+
bool isNotFound = false;
162185
// Find out the first child which is displaying
163186
var targetFirstChild = firstChild;
164187
var lastFirstGroupChildWidget = targetFirstChild;
@@ -171,9 +194,25 @@ class ObserverCore {
171194
)) {
172195
/// Entering here means it is not the target object
173196
RenderBox? nextChild = _obj.childAfter(targetFirstChild);
174-
if (nextChild == null) break;
197+
if (nextChild == null) {
198+
isNotFound = true;
199+
break;
200+
}
175201
targetFirstChild = nextChild;
176202
}
203+
204+
// The first child being displayed is not found, indicating that the
205+
// ScrollView is not visible.
206+
if (isNotFound) {
207+
return GridViewObserveModel(
208+
sliverGrid: _obj,
209+
viewport: viewport,
210+
visible: false,
211+
firstGroupChildList: [],
212+
displayingChildModelList: [],
213+
);
214+
}
215+
177216
if (targetFirstChild is! RenderIndexedSemantics) return null;
178217
lastFirstGroupChildWidget = targetFirstChild;
179218

test/sliver_observer_test.dart

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ void main() {
467467
late SliverObserverController observerController;
468468
late Widget widget;
469469
BuildContext? _sliverHeaderListCtx;
470+
BuildContext? _sliverHeaderGridCtx;
470471
BuildContext? _sliverBodyListCtx;
471472
BuildContext? _sliverBodyGridCtx;
472473
GlobalKey appBarKey = GlobalKey();
@@ -551,6 +552,22 @@ void main() {
551552
),
552553
itemExtent: 50,
553554
),
555+
SliverGrid.builder(
556+
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
557+
crossAxisCount: 2,
558+
mainAxisSpacing: 10.0,
559+
crossAxisSpacing: 10.0,
560+
childAspectRatio: 2.0,
561+
),
562+
itemBuilder: (context, index) {
563+
if (_sliverHeaderGridCtx != context) {
564+
_sliverHeaderGridCtx = context;
565+
nestedScrollUtil?.headerSliverContexts.add(context);
566+
}
567+
return Text("Item $index");
568+
},
569+
itemCount: 10,
570+
),
554571
];
555572
},
556573
body: Builder(builder: (context) {
@@ -587,6 +604,7 @@ void main() {
587604
sliverContexts: () {
588605
return [
589606
if (_sliverHeaderListCtx != null) _sliverHeaderListCtx!,
607+
if (_sliverHeaderGridCtx != null) _sliverHeaderGridCtx!,
590608
if (_sliverBodyListCtx != null) _sliverBodyListCtx!,
591609
if (_sliverBodyGridCtx != null) _sliverBodyGridCtx!,
592610
];
@@ -610,6 +628,7 @@ void main() {
610628
tearDown(() {
611629
outerScrollController.dispose();
612630
_sliverHeaderListCtx = null;
631+
_sliverHeaderGridCtx = null;
613632
_sliverBodyListCtx = null;
614633
_sliverBodyGridCtx = null;
615634
});
@@ -758,7 +777,7 @@ void main() {
758777
(tester) async {
759778
resetAll();
760779
await tester.pumpWidget(widget);
761-
expect(nestedScrollUtil?.headerSliverContexts.length, 1);
780+
expect(nestedScrollUtil?.headerSliverContexts.length, 2);
762781
expect(nestedScrollUtil?.bodySliverContexts.length, 2);
763782
expect(nestedScrollUtil?.remainingSliverContext == null, true);
764783
expect(nestedScrollUtil?.remainingSliverRenderObj == null, true);
@@ -774,6 +793,83 @@ void main() {
774793
expect(nestedScrollUtil?.remainingSliverRenderObj, null);
775794
},
776795
);
796+
797+
testWidgets(
798+
'Check the observed data when the sliver in the header is not visible',
799+
(tester) async {
800+
resetAll();
801+
await tester.pumpWidget(widget);
802+
await observerController.dispatchOnceObserve(
803+
sliverContext: _sliverHeaderListCtx!,
804+
);
805+
var headerListObservationResult =
806+
(resultMap[_sliverHeaderListCtx] as ListViewObserveModel);
807+
expect(
808+
headerListObservationResult.displayingChildIndexList,
809+
isNotEmpty,
810+
);
811+
812+
nestedScrollUtil?.jumpTo(
813+
nestedScrollViewKey: nestedScrollViewKey,
814+
observerController: observerController,
815+
sliverContext: _sliverHeaderGridCtx,
816+
position: NestedScrollUtilPosition.header,
817+
index: 0,
818+
offset: (targetOffset) {
819+
return calcPersistentHeaderExtent(
820+
offset: targetOffset,
821+
widgetKey: appBarKey,
822+
);
823+
},
824+
);
825+
await tester.pumpAndSettle();
826+
await tester.pump(observerController.observeIntervalForScrolling);
827+
828+
headerListObservationResult =
829+
(resultMap[_sliverHeaderListCtx] as ListViewObserveModel);
830+
expect(
831+
headerListObservationResult.displayingChildIndexList,
832+
isEmpty,
833+
);
834+
835+
var headerGridObservationResult =
836+
(resultMap[_sliverHeaderGridCtx] as GridViewObserveModel);
837+
expect(
838+
headerGridObservationResult.firstGroupChildList.first.index,
839+
0,
840+
);
841+
842+
nestedScrollUtil?.jumpTo(
843+
nestedScrollViewKey: nestedScrollViewKey,
844+
observerController: observerController,
845+
sliverContext: _sliverBodyListCtx,
846+
position: NestedScrollUtilPosition.body,
847+
index: 0,
848+
offset: (targetOffset) {
849+
return calcPersistentHeaderExtent(
850+
offset: targetOffset,
851+
widgetKey: appBarKey,
852+
);
853+
},
854+
);
855+
await tester.pumpAndSettle();
856+
await tester.pump(observerController.observeIntervalForScrolling);
857+
858+
var bodyListObservationResult =
859+
(resultMap[_sliverBodyListCtx] as ListViewObserveModel);
860+
expect(
861+
bodyListObservationResult.firstChild?.index,
862+
0,
863+
);
864+
865+
headerGridObservationResult =
866+
(resultMap[_sliverHeaderGridCtx] as GridViewObserveModel);
867+
expect(
868+
headerGridObservationResult.displayingChildIndexList,
869+
isEmpty,
870+
);
871+
},
872+
);
777873
},
778874
);
779875

0 commit comments

Comments
 (0)