颤振未来的 json 列表定义为最终列表并停止更新它



我可以从服务器获取JSON响应并列出。现在我想向该列表添加一个过滤器。

为此,我遵循了一个在线教程。 在该教程中,"duplicateItems"变量已创建为final。请参阅代码:

final duplicateItems = List<String>.generate(10000, (i) => "Item $i");
var items = List<String>();

但就我而言,由于我使用 Future 方法从服务器获取列表,我不能或我不知道将该变量设为最终变量。请参阅代码:

class _ListServiceProvidersState extends State<ListServiceProviders> {  
List items;
List duplicateItems;  
@override
void initState() {
super.initState();
getSharedValues();
}
getSharedValues() async {
bool value = await sharedPreferenceService.getSharedPreferencesInstance();
if (value) {
token = await sharedPreferenceService.token;
fetchServices();
} else {
commonModelServices.showMessage(
'You must log in before use the services', _scaffoldKey, Colors.red);
Navigator.pushNamed(
context,
'/LoginPage',
);
}
}
Future<String> fetchServices() async {
SchedulerBinding.instance.addPostFrameCallback((_) {
commonModelServices.onLoading(context);
});
final response = await http.get(
'API URL?category_id=$catId&city=$cityId&latitude=$latitude&longitude=$longitude');
setState(() {
commonModelServices.offLoading(context);
var resBody = json.decode(response.body);
if (resBody['success'] == true) {
setState(() {
duplicateItems = resBody['data']['data'];
items = duplicateItems;
});
}
});
return "Success";
}

这是我的过滤功能

void filterSearchResults(String query) {
List dummySearchList = List();
print('Original List');
dummySearchList.addAll(duplicateItems);
print(dummySearchList);
print('Search Query');
print(query);
if (query.isNotEmpty) {
print('search query not empty');
List dummyListData = List();
print('Start of the loop');
dummySearchList.forEach((item) {
print('List single item');
print(item);
if (item['name'].contains(query)) {
print('Item contain search query');
dummyListData.add(item);
}
});
print('End of the loop');
setState(() {
print('Clear duplicated List');
items.clear();
print('Set searched results');
items.addAll(dummyListData);
});
return;
} else {
print('Search query empty');
setState(() {
print('Clear prevoius searched in duplicate list');
items.clear();
print('Add Original List to duplicate');
items.addAll(duplicateItems);
});
}
}

筛选器按预期方式对搜索字段中的第一个字母工作。 但是对于下一次按键,当 filterSearchResults 函数执行时,原始列表也会更新为第一次按键的搜索结果。因此,它从以前的搜索结果中搜索搜索词,而不是从原始列表中搜索搜索词。所以,结果是错误的。

我想在搜索后保持原始变量"重复项目"不变。

你能告诉我这里缺少什么吗?

供您参考,我将在下面提供完整的代码。

import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_healthcare_app/src/theme/extention.dart';
import 'package:flutter_healthcare_app/src/theme/light_color.dart';
import 'package:flutter_healthcare_app/src/theme/text_styles.dart';
import 'package:flutter_healthcare_app/src/theme/theme.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_healthcare_app/src/model/shared_pref_model.dart';
import 'package:flutter_healthcare_app/src/model/common_model.dart';
class ListServiceProviders extends StatefulWidget {
ListServiceProviders({Key key}) : super(key: key);
@override
_ListServiceProvidersState createState() => _ListServiceProvidersState();
}
class _ListServiceProvidersState extends State<ListServiceProviders> {
TextEditingController editingController = TextEditingController();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
SharedPreferenceService sharedPreferenceService = SharedPreferenceService();
CommonModel commonModelServices = CommonModel();
List items;
List duplicateItems;
String token;
String cityId;
int catId;
String latitude;
String longitude;
@override
void initState() {
super.initState();
getSharedValues();
}
getSharedValues() async {
bool value = await sharedPreferenceService.getSharedPreferencesInstance();
if (value) {
token = await sharedPreferenceService.token;
cityId = await sharedPreferenceService.cityId;
catId = await sharedPreferenceService.catId;
latitude = await sharedPreferenceService.latitude;
longitude = await sharedPreferenceService.longitude;
fetchServices();
} else {
commonModelServices.showMessage(
'You must log in before use the services', _scaffoldKey, Colors.red);
Navigator.pushNamed(
context,
'/LoginPage',
);
}
}
Future<String> fetchServices() async {
SchedulerBinding.instance.addPostFrameCallback((_) {
commonModelServices.onLoading(context);
});
final response = await http.get(
'API URL?category_id=$catId&city=$cityId&latitude=$latitude&longitude=$longitude');
setState(() {
commonModelServices.offLoading(context);
var resBody = json.decode(response.body);
if (resBody['success'] == true) {
setState(() {
duplicateItems = resBody['data']['data'];
items = duplicateItems;
});
}
});
return "Success";
}
void filterSearchResults(String query) {
List dummySearchList = List();
print('Original List');
dummySearchList.addAll(duplicateItems);
print(dummySearchList);
print('Search Query');
print(query);
if (query.isNotEmpty) {
print('search query not empty');
List dummyListData = List();
print('Start of the loop');
dummySearchList.forEach((item) {
print('List single item');
print(item);
if (item['name'].contains(query)) {
print('Item contain search query');
dummyListData.add(item);
}
});
print('End of the loop');
setState(() {
print('Clear duplicated List');
items.clear();
print('Set searched results');
items.addAll(dummyListData);
});
return;
} else {
print('Search query empty');
setState(() {
print('Clear prevoius searched in duplicate list');
items.clear();
print('Add Original List to duplicate');
items.addAll(duplicateItems);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: commonModelServices.appBar(context),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
child: _header(),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
filterSearchResults(value);
},
controller: editingController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)))),
),
),
Container(
height: AppTheme.fullHeight(context),
child: new ListView.builder(
itemCount: items == null ? 0 : items.length,
itemBuilder: (BuildContext context, int index) {
return _categoryListView(index, items, context);
})),
],
)));
}
Widget _header() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Categories", style: TextStyles.titleM),
],
).p16;
}
/*  Widget _doctorsList(index, data, context) {
}*/
Widget _categoryListView(index, model, context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20)),
boxShadow: <BoxShadow>[
BoxShadow(
offset: Offset(4, 4),
blurRadius: 10,
color: LightColor.grey.withOpacity(.2),
),
BoxShadow(
offset: Offset(-3, 0),
blurRadius: 15,
color: LightColor.grey.withOpacity(.1),
)
],
),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 18, vertical: 8),
child: ListTile(
contentPadding: EdgeInsets.all(0),
leading: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(13)),
child: Container(
height: 55,
width: 55,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: randomColor(),
image: DecorationImage(
image: NetworkImage(model[index]['image'].toString()),
fit: BoxFit.cover,
),
),
/*child: Image.asset(
model[index]['image'].toString(),
height: 50,
width: 50,
fit: BoxFit.contain,
),*/
),
),
title: Text(model[index]['name'], style: TextStyles.title.bold),
subtitle: Text(
model[index]['description'],
style: TextStyles.bodySm.subTitleColor.bold,
),
trailing: Icon(
Icons.keyboard_arrow_right,
size: 30,
color: Theme.of(context).primaryColor,
),
),
).ripple(() {
Navigator.pushNamed(context, "/DetailPage", arguments: model);
}, borderRadius: BorderRadius.all(Radius.circular(20))),
);
}
void _showCategoryListPage(selectedCategory, catId, context) {
sharedPreferenceService.setCatId(catId);
Navigator.pushNamed(
context,
'/SelectServiceProvider',
);
}
Color randomColor() {
var random = Random();
final colorList = [
Theme.of(context).primaryColor,
LightColor.orange,
LightColor.green,
LightColor.grey,
LightColor.lightOrange,
LightColor.skyBlue,
LightColor.titleTextColor,
Colors.red,
Colors.brown,
LightColor.purpleExtraLight,
LightColor.skyBlue,
];
var color = colorList[random.nextInt(colorList.length)];
return color;
}
}

我在谷歌颤振社区得到了答案。我在这里分享它,供其他人将来使用。

只有一行要更新。

当我只是这样做时

setState(() {
duplicateItems = resBody['data']['data'];
items = duplicateItems;
});

它只创建一个引用变量。因此,当我更新项目变量时,它也会自动更新重复项变量。

所以我必须像下面这样更新它。因此,两者都作为两个不同的列表工作。

duplicateItems = List.from(items);

所以完整的代码如下所示。

setState(() {
commonModelServices.offLoading(context);
var resBody = json.decode(response.body);
if (resBody['success'] == true) {
setState(() {
items = resBody['data']['data'];
});
}
//items = duplicateItems;
duplicateItems = List.from(items);
});

同样的事情发生在我身上,也发生在你身上。匹配变量是相互引用它们,而不是复制它们的数据。非常感谢您发布您的解决方案。

我有

items = jsonResponse.data;
duplicateItems = items;

它引用了 items 变量,但不复制数据。

正确的就是你说的

items = jsonResponse.data;
duplicateItems = List.from(items);

所以过滤器工作。

原始教程是

https://karthikponnam.medium.com/flutter-search-in-listview-1ffa40956685

非常感谢您发布您的解决方案。 解决方案基本亲爱的沃森

最新更新