[Flutter component collection] NotificationListener | August update challenge

preface:

This is the first day that I participated in the challenge of Gengwen in August. See the details of the activity: August Gengwen challenge . In order to meet the challenge of nuggets in August, I am going to select 31 components that have not been introduced before this month for comprehensive analysis and attribute introduction. These articles will be used as important materials for the collection of fluent components in the future. I hope I can stick to it. Your support will be my biggest motivation~

This series

Component article

list

1. Introduction

When studying the source code of ScrollView, I had a very interesting harvest. Here, as an introduction, we introduce the NotificationListener component. The following is a part of the source code of ScrollView#build. It can be seen that when the keyboarddisassbehavior is onDrag, a NotificationListener component will be nested in the upper layer of the built component and processed logically in onNotification.

Where scrollviewkeyboarddisassbehavior is an enumeration with only two elements.

enum ScrollViewKeyboardDismissBehavior {
  manual,
  onDrag,
}

ListView inherits from ScrollView. The keyboarddisassbehavior parameter in the construct initializes the member defined in ScrollView. The core code of the test is as follows:

The effects of manual and onDrag are as follows: when the current keyboard pops up, if it is manual, the keyboard will not be actively hidden during the list sliding process. When it is onDrag, the keyboard will be actively hidden when sliding the list.

Through a small detail in the source code, we can clearly realize the value of notificationlister. It can monitor the sliding process and call back the relevant data for the user to process logically.

2. Get to know NotificationListener

Firstly, NotificationListener is a StatelessWidget that accepts a generic type of Notification family. A child component must be passed in the construction method to set the listening of onNotification.

The type of onNotification member is notificationlistenercallback < T >, which can be seen as a function type and returns bool value. The input parameter is a t generic object and must be a subclass of Notification. In other words, the function will call back a data and return an identification used to control a logic.

---->[NotificationListener#onNotification declaration]----
final NotificationListenerCallback<T>? onNotification;

typedef NotificationListenerCallback<T extends Notification> = 
                                               bool Function(T notification);

Since it is a StatelessWidget, the most important is the build method. However, it can be seen from the source code that the component directly returns the child passed in by the user, that is, it does not care about the construction logic of the component.

Finally, there is a private method in this class_ dispatch, the Notification object needs to be passed in this method. It can be seen that this is the trigger occasion of the onNotification method passed in by the user.

3. Recognize Notification

The above involves many notifications. If you don't understand this class, it's difficult to have a comprehensive understanding of notificationlister. Notification is an abstract class that does not inherit any classes. There are two common methods, visitAncestor and dispatch.

Since Notification is an abstract class, objects cannot be constructed directly. Therefore, the fluent framework naturally provides relevant implementation classes. The following are many implementation classes of Notification, including ScrollUpdateNotification in the introduction. In this way, we can know which notifications can be monitored.

4. Recognize the use of NotificationListener

For example, let's listen to ScrollUpdateNotification through NotificationListener, so that when sliding_ The onNotification callback can call back the notification sliding data. We can carry out relevant logical processing according to this object.

class ListViewDemo extends StatelessWidget {
  const ListViewDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollUpdateNotification>(
      onNotification: _onNotification,
      child: ListView(
          children: List.generate(
              60,
              (index) => ItemBox(index: index, )).toList()),
    );
  }

  bool _onNotification(ScrollUpdateNotification notification) {
    print('====dragDetails:${notification.dragDetails}'
        '====pixels:${notification.metrics.pixels}');
    return false;
  }
}

The test item monomer is as follows, which is displayed by ItemBox component.

class ItemBox extends StatelessWidget {
  final int index;

  const ItemBox({Key? key, required this.index}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      decoration: BoxDecoration(
          border: Border(
              bottom: BorderSide(
        width: 1 / window.devicePixelRatio,
      ))),
      height: 56,
      child: Text(
        'The first $index individual',
        style: TextStyle(fontSize: 20),
      ),
    );
  }
}

We can listen to any Notification type, such as the following OverscrollNotification. This listening will be triggered when the list slides to the top or bottom. The out of bounds size overscroll can be obtained in the callback data.

class ListViewDemo extends StatelessWidget {
  const ListViewDemo({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return NotificationListener<OverscrollNotification>(
      onNotification: _onNotification,
      child: ListView(
          children: List.generate(
              60,
              (index) => ItemBox( index: index,)).toList()),
    );
  }
  bool _onNotification(OverscrollNotification notification) {
    print('====dragDetails:${notification.dragDetails}'
   '====pixels:${notification.metrics.pixels}'
   '=====overscroll:${notification.overscroll}');
    return false;
  }
}

In addition to listening to a certain Notification, we can also listen to multiple notifications through the parent. The following is the code for listening to the top-level Abstract Notification class. The log after sliding up is as follows. It can be seen that multiple types of Notification notifications can be monitored at the same time. We can distinguish them by type judgment.

class ListViewDemo extends StatelessWidget {
  const ListViewDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return NotificationListener<Notification>(
      onNotification: _onNotification,
      child: ListView(
          children: List.generate(
              60,
              (index) => ItemBox( index: index,)).toList()),
    );
  }

  bool _onNotification(Notification notification) {
    print('====Notification type:${notification.runtimeType}======');
    return false;
  }
}

5. Use of NotificationListener in the source code

The most classic is the use of NotificationListener in the Scrollbar source code. It listens to five notifications of ScrollNotification through_ handleScrollNotification.

In this way, as long as a Scrollbar is nested outside the ListView, an indicator can appear on the right during sliding.

Scrollbar(
  child: ListView(
      children: List.generate(
          60,
          (index) => ItemBox(index: index,)).toList()),
),

In addition, the RefreshIndicator component is also implemented internally based on listening to ScrollNotification and OverscrollIndicatorNotification notifications.

6. Function of return value in notificationlistener listening

As can be seen from the source code, when false is returned, it means that the notification can continue to be distributed to the upper node. Conversely, it means that the notification is truncated.

For example, when the listener returns true, it will be placed below the notificationscreen code. In this way, when the sliding event of the ListView is distributed upward, it is intercepted when it reaches the notificationlister, so it can no longer be uploaded to the listener in the Scrollbar. That means Scrollbar doesn't work.

In the sliding system of Flutter, through the distribution and monitoring of Notification, we can monitor the sliding of components anywhere. In this way, the sliding events are greatly decoupled. As for the specific process of sliding Notification, it can not be introduced in a word. As an ordinary user, it is enough to know this. My fourth volume, the exploration of Flutter sliding - a perfect combination, will comprehensively analyze the source code implementation of Flutter sliding system. Please look forward to it.

Added by Promark on Tue, 08 Mar 2022 10:49:46 +0200