Issue
I am trying to create a search widget in flutter, for list I used the application list using device_apps (https://pub.dev/packages/device_apps). But Im getting an error "type ‘Future’ is not a subtype of type ‘List?’" . To create the search widget I used help from this link.
Here is my code:
import 'dart:async';
import 'package:device_apps/device_apps.dart';
import 'package:flutter/material.dart';
class SearchWidget extends StatelessWidget {
SearchWidget({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
TextField(onChanged: _filter),
StreamBuilder<List<Application>>(
initialData: lelist(),
stream: _stream,
builder:
(BuildContext context, AsyncSnapshot<List<Application>> snapshot) {
print(snapshot.data);
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data[index].appName);
},
);
},
)
],
),
);
}
}
StreamController<List<Application>> _streamController = StreamController<List<Application>>();
Stream<List<Application>> get _stream => _streamController.stream;
_filter(String searchQuery) {
List<Application> _filteredList = lelist()
.where((Application app) => app.appName.toLowerCase().contains(searchQuery.toLowerCase()))
.toList();
_streamController.sink.add(_filteredList);
}
lelist() async {
List<Application> _dataFromQuerySnapShot = await DeviceApps.getInstalledApplications(includeAppIcons: true);
_dataFromQuerySnapShot.sort((a, b) {
return a.appName.toString().toLowerCase().compareTo(b.appName.toString().toLowerCase());
});
return _dataFromQuerySnapShot;
}
Solution
I think there it is unnecessary to load and sort the installed apps on every keystroke and therefore put all of this logic into initState. This also makes your _filter
function synchronous.
import 'dart:async';
import 'package:device_apps/device_apps.dart';
import 'package:flutter/material.dart';
class SearchWidget extends StatefulWidget {
SearchWidget({Key key}) : super(key: key);
@override
_SearchWidgetState createState() => _SearchWidgetState();
}
class _SearchWidgetState extends State<SearchWidget> {
final _streamController = StreamController<List<Application>>();
List<Application> _dataFromQuerySnapShot;
Stream<List<Application>> get _stream => _streamController.stream;
@override
void initState() {
DeviceApps.getInstalledApplications(includeAppIcons: true)
.then((List<Application> apps) {
_dataFromQuerySnapShot = apps;
_dataFromQuerySnapShot.sort((a, b) {
return a.appName
.toString()
.toLowerCase()
.compareTo(b.appName.toString().toLowerCase());
});
_streamController.sink.add(_dataFromQuerySnapShot);
});
super.initState();
}
@override
void dispose() {
_streamController.close();
super.dispose();
}
_filter(String searchQuery) {
final filteredApplications = _dataFromQuerySnapShot
.where((Application app) =>
app.appName.toLowerCase().contains(searchQuery.toLowerCase()))
.toList();
_streamController.sink.add(filteredApplications);
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
TextField(onChanged: _filter),
StreamBuilder<List<Application>>(
stream: _stream,
builder: (BuildContext context,
AsyncSnapshot<List<Application>> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return snapshot.data.isEmpty
? Center(child: Text('Empty'))
: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data[index].appName);
},
);
},
)
],
),
);
}
}
Answered By – hnnngwdlch
Answer Checked By – David Marino (FlutterFixes Volunteer)