constructor(params: ParamType) {
    invariant(
      params && typeof params.rowHasChanged === 'function',
      'Must provide a rowHasChanged function.',
    );
    this._rowHasChanged = params.rowHasChanged;
    this._getRowData = params.getRowData || defaultGetRowData;
    this._sectionHeaderHasChanged = params.sectionHeaderHasChanged;
    this._getSectionHeaderData =
      params.getSectionHeaderData || defaultGetSectionHeaderData;

    this._dataBlob = null;
    this._dirtyRows = [];
    this._dirtySections = [];
    this._cachedRowCount = 0;

    // These two private variables are accessed by outsiders because ListView
    // uses them to iterate over the data in this class.
    this.rowIdentities = [];
    this.sectionIdentities = [];
  }
You can provide custom extraction and `hasChanged` functions for section
headers and rows.  If absent, data will be extracted with the
`defaultGetRowData` and `defaultGetSectionHeaderData` functions.

The default extractor expects data of one of the following forms:

     { sectionID_1: { rowID_1: <rowData1>, ... }, ... }

   or

     { sectionID_1: [ <rowData1>, <rowData2>, ... ], ... }

   or

     [ [ <rowData1>, <rowData2>, ... ], ... ]

The constructor takes in a params argument that can contain any of the
following:

- getRowData(dataBlob, sectionID, rowID);
- getSectionHeaderData(dataBlob, sectionID);
- rowHasChanged(prevRowData, nextRowData);
- sectionHeaderHasChanged(prevSectionData, nextSectionData);