如何在未来数据上重新加载屏幕

问题描述

我有TabBarView,带有六个标签。 我试图在第一个标签中显示所有已安装的应用。

即使在apps被填充后,CircularProgressIndicator也会显示。重新访问第一个标签后,应用程序即会列出。

AppScreenC被称为第一个标签。

final model = AppModel();

class AppScreenC extends StatefulWidget {
  @override
  _AppScreenCState createState() => _AppScreenCState();
}

class _AppScreenCState extends State<AppScreenC> {
  List<Application> apps = model.loadedApps();
      
  @override
  Widget build(BuildContext context) => _buildApps();

  Widget _buildApps() => apps != null
      ? ListView.builder(
          itemCount: apps.length,itemBuilder: (BuildContext context,int index) =>
              _buildRow(apps[index]))
      : Center(child: CircularProgressIndicator());

  Widget _buildRow(ApplicationWithIcon app) {
    final saved = model.getApps().contains(app.apkFilePath);
    return ListTile(
      leading: Image.memory(app.icon,height: 40),trailing: saved
          ? Icon(Icons.check_circle,color: Colors.deepPurple[400])
          : Icon(Icons.check_circle_outline),title: Text(app.appName),onTap: () => setState(() => saved
          ? model.removeApp(app.apkFilePath)
          : model.addApp(app.apkFilePath)),);
  }
}

AppModel类具有所有必需的方法。

  class AppModel{
  final _saved = Set<String>();
  List<Application> apps;

  AppModel() {
    loadApps();
  }

  Set<String> getApps() {
    return _saved;
  }

  addApp(String apkPath) {
    _saved.add(apkPath);
  }

  removeApp(String apkPath) {
    _saved.remove(apkPath);
  }

  loadApps() async {
    apps = await DeviceApps.getInstalledApplications(
        onlyAppsWithLaunchIntent: true,includeSystemApps: true,includeAppIcons: true);
    apps.sort((a,b) => a.appName.compareTo(b.appName));
  }

  loadedApps() => apps;
}

之所以发生这种情况,是因为在第一次调用该屏幕时apps为空。它在后台加载应用程序。再次访问屏幕时,将显示应用。

欢迎任何帮助

解决方法

完成功能后,您可以调用setState()。您需要更改loadedApp以返回Future

class AppScreenC extends StatefulWidget {
  @override
  _AppScreenCState createState() => _AppScreenCState();
}

class _AppScreenCState extends State<AppScreenC> {
  @override
 void initState(){
 super.initState();
 model.loadApps().then((loadedApps){ //loadApps() will return apps and you don't need loadedApps() method anymore
 setState((){ //rebuilds the screen
  apps = loadedApps
   })});
}
      
  @override
  Widget build(BuildContext context) => _buildApps();

  Widget _buildApps() => apps != null
      ? ListView.builder(
          itemCount: apps.length,itemBuilder: (BuildContext context,int index) =>
              _buildRow(apps[index]))
      : Center(child: CircularProgressIndicator());

  Widget _buildRow(ApplicationWithIcon app) {
    final saved = model.getApps().contains(app.apkFilePath);
    return ListTile(
      leading: Image.memory(app.icon,height: 40),trailing: saved
          ? Icon(Icons.check_circle,color: Colors.deepPurple[400])
          : Icon(Icons.check_circle_outline),title: Text(app.appName),onTap: () => setState(() => saved
          ? model.removeApp(app.apkFilePath)
          : model.addApp(app.apkFilePath)),);
  }
}

您的AppModel如下所示:

class AppModel{
  final _saved = Set<String>();
  List<Application> apps;

  AppModel() {
    loadApps();
  }

  Set<String> getApps() {
    return _saved;
  }

  addApp(String apkPath) {
    _saved.add(apkPath);
  }

  removeApp(String apkPath) {
    _saved.remove(apkPath);
  }

  Future loadApps() async {
    apps = await DeviceApps.getInstalledApplications(
        onlyAppsWithLaunchIntent: true,includeSystemApps: true,includeAppIcons: true);
    apps.sort((a,b) => a.appName.compareTo(b.appName));
    return Future.value(apps);
  }

}

您也可以按照评论中的建议使用FutureBuilder

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...