Flutter 应用程序中的无限列表
Infinite List in Flutter Application
我正在将我的应用程序从 android 迁移到 flutter,直到现在我已经在 flutter 中使用了 ListView。我的问题是,是否有专门的技术来处理颤振中的大量数据?作为参考,您可以查看 android RecyclerView。它处理内存中的视图并回收其运行时。那么如何在Flutter中实现类似RecyclerView的功能呢?还是不需要颤振?
最简单的方法是使用 ListView.builder
而不指定 itemCount
参数。
这是最简单的例子:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Infinite List"),
),
body: ListView.builder(
itemBuilder: (context, index) {
return Text("$index");
},
),
);
}
}
稍后,您可以通过获取真实数据来增强这一点。您可以在等待新数据时在列表的最后一项显示 'CircularProgressIndicator'。
body: ListView.builder(
itemBuilder: (context, index) {
if (index < data.length) {
// Show your info
return Text("$index");
} else {
getMoreData();
return Center(child: CircularProgressIndicator());
}
},
itemCount: data.length + 1,
),
您可以看到我们通过添加索引来欺骗列表,并在显示最终索引时调用更多数据。
getMoreData()
将包括对 setState()
的调用以强制重建并考虑新数据。
显示数据列表是移动应用程序的基本模式。 Flutter 包含 ListView 小部件,使使用列表变得轻而易举。
我已经通过执行以下步骤解决了问题
- 使用 ListView 小部件
- ListView有四个构造函数Class
- 您必须使用 Builder 构造函数 (ListView.builder)
- 当你必须按需制作元素列表时使用构造函数
- 适用于具有大量(或无限)子项的列表视图
在这里你可以看到解决方案视频CLICK HERE
对于无限滚动 ListView 使用 infinite_scroll_pagination 包此包管理延迟加载并在用户向下滚动屏幕时显示项目页面。
添加依赖项
dependencies:
flutter:
sdk: flutter
infinite_scroll_pagination: ^2.3.0
在文件顶部添加对新库的导入:
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
使用示例
class CharacterListView extends StatefulWidget {
@override
_CharacterListViewState createState() => _CharacterListViewState();
}
class _CharacterListViewState extends State<CharacterListView> {
static const _pageSize = 20;
final PagingController<int, CharacterSummary> _pagingController =
PagingController(firstPageKey: 0);
@override
void initState() {
_pagingController.addPageRequestListener((pageKey) {
_fetchPage(pageKey);
});
super.initState();
}
Future<void> _fetchPage(int pageKey) async {
try {
final newItems = await RemoteApi.getCharacterList(pageKey, _pageSize);
final isLastPage = newItems.length < _pageSize;
if (isLastPage) {
_pagingController.appendLastPage(newItems);
} else {
final nextPageKey = pageKey + newItems.length;
_pagingController.appendPage(newItems, nextPageKey);
}
} catch (error) {
_pagingController.error = error;
}
}
@override
Widget build(BuildContext context) =>
// Don't worry about displaying progress or error indicators on screen; the
// package takes care of that. If you want to customize them, use the
// [PagedChildBuilderDelegate] properties.
PagedListView<int, CharacterSummary>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<CharacterSummary>(
itemBuilder: (context, item, index) => CharacterListItem(
character: item,
),
),
);
@override
void dispose() {
_pagingController.dispose();
super.dispose();
}
}
下面是一个基于 答案的简单无限列表小部件。它接受 itemBuilder
来构建当前项目,并接受 onRequest
回调以在用户滚动到底部时请求更多数据。
import 'package:flutter/material.dart';
typedef Future<List<T>> RequestFn<T>(int nextIndex);
typedef Widget ItemBuilder<T>(BuildContext context, T item, int index);
class InifiniteList<T> extends StatefulWidget {
final RequestFn<T> onRequest;
final ItemBuilder<T> itemBuilder;
const InifiniteList(
{Key? key, required this.onRequest, required this.itemBuilder})
: super(key: key);
@override
_InifiniteListState<T> createState() => _InifiniteListState<T>();
}
class _InifiniteListState<T> extends State<InifiniteList<T>> {
List<T> items = [];
bool end = false;
_getMoreItems() async {
final moreItems = await widget.onRequest(items.length);
if (!mounted) return;
if (moreItems.isEmpty) {
setState(() => end = true);
return;
}
setState(() => items = [...items, ...moreItems]);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
if (index < items.length) {
return widget.itemBuilder(context, items[index], index);
} else if (index == items.length && end) {
return const Center(child: Text('End of list'));
} else {
_getMoreItems();
return const SizedBox(
height: 80,
child: Center(child: CircularProgressIndicator()),
);
}
},
itemCount: items.length + 1,
);
}
}
用法
child: InifiniteList<String>(
onRequest: requestItems,
itemBuilder: (context, item, index) => Container(
padding: const EdgeInsets.all(30),
color: index % 2 == 0 ? Colors.purple.shade100 : Colors.lime.shade100,
child: Text(item, style: Theme.of(context).textTheme.headline6),
),
),
// normally this is the place where you request the next batch of items
// on the network.
Future<List<String>> requestItems(int nextIndex) {
const pageSize = 15;
var result = List<String>.generate(pageSize, (i) => "Item: ${nextIndex + i + 1}");
return Future<List<String>>.delayed(
const Duration(milliseconds: 500),
() => result,
);
}
Live Demo
我正在将我的应用程序从 android 迁移到 flutter,直到现在我已经在 flutter 中使用了 ListView。我的问题是,是否有专门的技术来处理颤振中的大量数据?作为参考,您可以查看 android RecyclerView。它处理内存中的视图并回收其运行时。那么如何在Flutter中实现类似RecyclerView的功能呢?还是不需要颤振?
最简单的方法是使用 ListView.builder
而不指定 itemCount
参数。
这是最简单的例子:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Infinite List"),
),
body: ListView.builder(
itemBuilder: (context, index) {
return Text("$index");
},
),
);
}
}
稍后,您可以通过获取真实数据来增强这一点。您可以在等待新数据时在列表的最后一项显示 'CircularProgressIndicator'。
body: ListView.builder(
itemBuilder: (context, index) {
if (index < data.length) {
// Show your info
return Text("$index");
} else {
getMoreData();
return Center(child: CircularProgressIndicator());
}
},
itemCount: data.length + 1,
),
您可以看到我们通过添加索引来欺骗列表,并在显示最终索引时调用更多数据。
getMoreData()
将包括对 setState()
的调用以强制重建并考虑新数据。
显示数据列表是移动应用程序的基本模式。 Flutter 包含 ListView 小部件,使使用列表变得轻而易举。
我已经通过执行以下步骤解决了问题
- 使用 ListView 小部件
- ListView有四个构造函数Class
- 您必须使用 Builder 构造函数 (ListView.builder)
- 当你必须按需制作元素列表时使用构造函数
- 适用于具有大量(或无限)子项的列表视图
在这里你可以看到解决方案视频CLICK HERE
对于无限滚动 ListView 使用 infinite_scroll_pagination 包此包管理延迟加载并在用户向下滚动屏幕时显示项目页面。
添加依赖项
dependencies:
flutter:
sdk: flutter
infinite_scroll_pagination: ^2.3.0
在文件顶部添加对新库的导入:
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
使用示例
class CharacterListView extends StatefulWidget {
@override
_CharacterListViewState createState() => _CharacterListViewState();
}
class _CharacterListViewState extends State<CharacterListView> {
static const _pageSize = 20;
final PagingController<int, CharacterSummary> _pagingController =
PagingController(firstPageKey: 0);
@override
void initState() {
_pagingController.addPageRequestListener((pageKey) {
_fetchPage(pageKey);
});
super.initState();
}
Future<void> _fetchPage(int pageKey) async {
try {
final newItems = await RemoteApi.getCharacterList(pageKey, _pageSize);
final isLastPage = newItems.length < _pageSize;
if (isLastPage) {
_pagingController.appendLastPage(newItems);
} else {
final nextPageKey = pageKey + newItems.length;
_pagingController.appendPage(newItems, nextPageKey);
}
} catch (error) {
_pagingController.error = error;
}
}
@override
Widget build(BuildContext context) =>
// Don't worry about displaying progress or error indicators on screen; the
// package takes care of that. If you want to customize them, use the
// [PagedChildBuilderDelegate] properties.
PagedListView<int, CharacterSummary>(
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<CharacterSummary>(
itemBuilder: (context, item, index) => CharacterListItem(
character: item,
),
),
);
@override
void dispose() {
_pagingController.dispose();
super.dispose();
}
}
下面是一个基于 itemBuilder
来构建当前项目,并接受 onRequest
回调以在用户滚动到底部时请求更多数据。
import 'package:flutter/material.dart';
typedef Future<List<T>> RequestFn<T>(int nextIndex);
typedef Widget ItemBuilder<T>(BuildContext context, T item, int index);
class InifiniteList<T> extends StatefulWidget {
final RequestFn<T> onRequest;
final ItemBuilder<T> itemBuilder;
const InifiniteList(
{Key? key, required this.onRequest, required this.itemBuilder})
: super(key: key);
@override
_InifiniteListState<T> createState() => _InifiniteListState<T>();
}
class _InifiniteListState<T> extends State<InifiniteList<T>> {
List<T> items = [];
bool end = false;
_getMoreItems() async {
final moreItems = await widget.onRequest(items.length);
if (!mounted) return;
if (moreItems.isEmpty) {
setState(() => end = true);
return;
}
setState(() => items = [...items, ...moreItems]);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
if (index < items.length) {
return widget.itemBuilder(context, items[index], index);
} else if (index == items.length && end) {
return const Center(child: Text('End of list'));
} else {
_getMoreItems();
return const SizedBox(
height: 80,
child: Center(child: CircularProgressIndicator()),
);
}
},
itemCount: items.length + 1,
);
}
}
用法
child: InifiniteList<String>(
onRequest: requestItems,
itemBuilder: (context, item, index) => Container(
padding: const EdgeInsets.all(30),
color: index % 2 == 0 ? Colors.purple.shade100 : Colors.lime.shade100,
child: Text(item, style: Theme.of(context).textTheme.headline6),
),
),
// normally this is the place where you request the next batch of items
// on the network.
Future<List<String>> requestItems(int nextIndex) {
const pageSize = 15;
var result = List<String>.generate(pageSize, (i) => "Item: ${nextIndex + i + 1}");
return Future<List<String>>.delayed(
const Duration(milliseconds: 500),
() => result,
);
}