如何在未来的数据上重新加载屏幕
How to reload screen on future data
我有 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 拥有所有必要的方法。
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 更改为 return a 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
我有 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 拥有所有必要的方法。
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 更改为 return a 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