_pages.elementAt(_selectedIndex)在flutter中检查并授予存储权限后未正确显示

smtd7mpg  于 2023-05-19  发布在  Flutter
关注(0)|答案(1)|浏览(115)

我添加了一个条件块,当权限状态返回为拒绝时,RequestPermissionPage小部件将在其中显示。它显示了RequestPermissionPage小部件,请求权限的按钮也按预期工作,但在给予权限后,主页仍然无法正常显示。
我正在对provider使用permission_handler。下面是我的代码:

class _HomeState extends State<Home> {
  final AppPermissionState _perm = AppPermissionState();
  final List<Widget> _pages = [const HomePage(), RecentPage(), StoragePage()];
  @override
  void initState() {
    super.initState();
    _perm.checkPermissionStatus();
  }

  int _selectedIndex = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _perm.permissionStatus.isGranted
          ? _pages.elementAt(_selectedIndex) //this doesn't show after requesting
          : const RequestPermissionPage(), //this works as intended
      bottomNavigationBar: NavigationBar(
        destinations: const [
          NavigationDestination(
              icon: Icon(Icons.folder_open), label: "Library"),
          NavigationDestination(
              icon: Icon(Icons.timelapse_rounded), label: "Recent"),
          NavigationDestination(
              icon: Icon(Icons.storage_outlined), label: "Storage"),
        ],
        selectedIndex: _selectedIndex,
        labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
        onDestinationSelected: (value) {
          setState(() {
            _selectedIndex = value;
          });
        },
      ),
    );
  }
}
class RequestPermissionPage extends StatelessWidget {
  const RequestPermissionPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Consumer<AppPermissionState>(
      builder: (context, permissionStateValue, child) {
        return Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              const Padding(
                padding: EdgeInsets.all(16.0),
                child: Text("This feature require storage permission"),
              ),
              FilledButton.tonal(
                onPressed: () {
                  permissionStateValue.requestPermission(); //this works as intended too
                },
                child: const Text("Grant Permission"),
              )
            ],
          ),
        );
      },
    );
  }
}

权限提供者:

class AppPermissionState extends ChangeNotifier {
  PermissionStatus _permissionStatus = PermissionStatus.denied;

  PermissionStatus get permissionStatus => _permissionStatus;

  Future<void> requestPermission() async {
    _permissionStatus = await Permission.manageExternalStorage.request();
    notifyListeners();
  }

  Future<void> checkPermissionStatus() async {
    _permissionStatus = await Permission.manageExternalStorage.status;
  }
}

在Android Q、S和T上测试
AndroidManifest.xml中已提及的权限

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

已尝试将AppPermissionState中的checkPermissionStatus()更改为以下代码

Future<void> checkPermissionStatus() async {
    await requestPermission();
    _permissionStatus = await Permission.manageExternalStorage.status;
    notifyListeners();
  }

应在授予权限后立即仅显示_pages.elementAt(_selectedIndex)中的内容,而不重新启动应用程序。
但即使在授予权限后仍显示RequestPermissionPage,奇怪的是,在重新启动应用程序后,我可以切换_pages中的元素,而RequestPermissionPage在更改底部导航栏页面后不显示,但每次打开应用程序时都会显示RequestPermissionPage。我该怎么解决?

ia2d9nvy

ia2d9nvy1#

解决了上述问题。我没有在build()外部调用AppPermissionState,而是在build()内部调用它:

Widget build(BuildContext context) {
    final _perm = Provider.of<AppPermissionState>(context);
    _perm.checkPermissionStatus();
    if (_perm.permissionStatus.isGranted) {
      return _buildHomePage(); //returns successfully when condition is true
    } else {
      return const RequestPermissionPage(); //returns successfully when condition is false
    }
  }

而在RequestPermissionPage中,事实证明不需要Consumer Builder。相反,在StatelessWidget类中将Cosumer builder替换为:

Widget build(BuildContext context) {
    final permissionStateValue = Provider.of<AppPermissionState>(context);
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const Padding(
              padding: EdgeInsets.all(16.0),
              child: Text("This feature require storage permission"),
            ),
            FilledButton.tonal(
              style: ButtonStyle(
                  alignment: Alignment.centerLeft,
                  padding: MaterialStateProperty.all(
                    const EdgeInsets.all(16.0),
                  ),
                  shape: MaterialStateProperty.all(
                    RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(16),
                    ),
                  )),
              onPressed: () {
                permissionStateValue.requestPermission();
              },
              child: const Text("Request Permission"),
            )
          ],
        ),
      ),
    );
  }

权限提供程序保持不变

class AppPermissionState extends ChangeNotifier {
  PermissionStatus _permissionStatus = PermissionStatus.denied;

  PermissionStatus get permissionStatus => _permissionStatus;

  Future<void> requestPermission() async {
    _permissionStatus = await Permission.manageExternalStorage.request();
    notifyListeners();
  }

  Future<void> checkPermissionStatus() async {
    _permissionStatus = await Permission.manageExternalStorage.status;
  }
}

相关问题