type 'Future<dynamic>' is not a subtype of type 'List<Application>?'

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)

Leave a Reply

Your email address will not be published. Required fields are marked *