英文:
_pages.elementAt(_selectedIndex) doesn't show up properly after checking and granting storage permission in flutter
问题
我添加了一个条件块,当权限状态返回为拒绝时,会显示RequestPermissionPage小部件。它显示RequestPermissionPage小部件,并且按钮也按预期工作,但在授予权限后,主页面仍然不会正确显示。
我正在使用permission_handler与provider。
这是我的代码:
class _HomeState extends State<Home> {
// ... 其他代码
}
class RequestPermissionPage extends StatelessWidget {
// ... 其他代码
}
class AppPermissionState extends ChangeNotifier {
// ... 其他代码
}
// ... 其他代码
Tried changing checkPermissionStatus() in AppPermissionState to the following code
Expected to show only the content in \_pages.elementAt(\_selectedIndex) right after granting permission and without restarting the app.
But shows RequestPermissionPage even after granting permission, strangely after restarting the app I can toggle elements in \_pages and RequestPermissionPage doesn't show after changing bottom navbar pages but RequestPermissionPage shows up every time app is opened. How do I fix it?
英文:
I added a condition block where RequestPermissionPage widget would show when permission status is returned as denied. It shows the RequestPermissionPage widget and the button to request permission also works as intended but after giving the permission, the main page still wont show properly.
I'm using permission_handler with provider.
Here is my code:
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"),
)
],
),
);
},
);
}
}
Permission provider:
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;
}
}
Tested on Android Q, S and T
Permissions already mentioned in 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" />
Tried changing checkPermissionStatus() in AppPermissionState to the following code
Future<void> checkPermissionStatus() async {
await requestPermission();
_permissionStatus = await Permission.manageExternalStorage.status;
notifyListeners();
}
Expected to show only the content in _pages.elementAt(_selectedIndex) right after granting permission and without restarting the app.
But shows RequestPermissionPage even after granting permission, strangely after restarting the app I can toggle elements in _pages and RequestPermissionPage doesn't show after changing bottom navbar pages but RequestPermissionPage shows up every time app is opened. How do I fix it?
答案1
得分: 0
以下是您提供的代码的中文翻译:
上述问题已解决。不再在build()
外部调用AppPermissionState
,而是在build()
内部调用它:
Widget build(BuildContext context) {
final _perm = Provider.of<AppPermissionState>(context);
_perm.checkPermissionStatus();
if (_perm.permissionStatus.isGranted) {
return _buildHomePage(); // 条件为true时返回成功
} else {
return const RequestPermissionPage(); // 条件为false时返回成功
}
}
在RequestPermissionPage
中,发现不需要使用Consumer
构建器。而是在StatelessWidget
类中用以下方式替换Cosumer
构建器:
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("此功能需要存储权限"),
),
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("请求权限"),
)
],
),
),
);
}
权限提供程序保持不变:
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;
}
}
英文:
The above problem is resolved. Instead of calling AppPermissionState
outside build()
, I had to call it inside 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
}
}
and in RequestPermissionPage
, turns out there isn't need for Consumer builder. Instead replaced Cosumer builder with this in a StatelessWidget
class:
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"),
)
],
),
),
);
}
The permission provider stays the same
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;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论