androidflutterfilepathriverpod

Flutter file_picker with Riverpod


I'm trying to learn Riverpod nowadays and I'm trying to use the file_picker package with it. Can't find a way to implement it in this code. I created two state notifiers that are supposed to hold values of the path and the isUserAborted values. In the example of the file_picker package they used setState with statefulWidget on the selectFolder method, but I'm wanting to use ConsumerWidget instead. How can I manage to do this? Have a good day!

import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class DirectoryPathNotifier extends StateNotifier<String?> {
  DirectoryPathNotifier() : super("NoPathSelectedYet");
}

class UserAbortedNotifier extends StateNotifier<bool> {
  UserAbortedNotifier() : super(false);
}

final directoryPathProvider =
    StateNotifierProvider<DirectoryPathNotifier, String?>((ref) {
  return DirectoryPathNotifier();
});

final userAbortedProvider =
    StateNotifierProvider<UserAbortedNotifier, bool>((ref) {
  return UserAbortedNotifier();
});

class CreamPath extends ConsumerWidget {
  CreamPath({super.key});

  List<PlatformFile>? _paths; //used
  String? directoryPath; //Used
  bool isLoading = false; //used
  bool userAborted = false; //Used

  Future<void> _selectFolder() async {
    String? path = await FilePicker.platform.getDirectoryPath();
    setState(() {
      directoryPath = path;
      userAborted = path == null;
    });
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {

return Scaffold(
  appBar: AppBar(
    title: const Text('File Picker example app'),
  ),
  body: Center(
    child: Padding(
      padding: const EdgeInsets.only(left: 10.0, right: 10.0),
      child: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(top: 50.0, bottom: 20.0),
              child: Column(
                children: <Widget>[
                  SizedBox(height: 10),
                  ElevatedButton(
                    onPressed: () => _selectFolder(),
                    child: const Text('Pick folder'),
                  ),
                  SizedBox(height: 10),
                  SizedBox(height: 10),
                ],
              ),
            ),
            Builder(
              builder: (BuildContext context) => isLoading
                  ? Padding(
                      padding: const EdgeInsets.only(bottom: 10.0),
                      child: const CircularProgressIndicator(),
                    )
                  : userAborted
                      ? Padding(
                          padding: const EdgeInsets.only(bottom: 10.0),
                          child: const Text(
                            'User has aborted the dialog',
                          ),
                        )
                      : directoryPath != null
                          ? ListTile(
                              title: const Text('Directory path'),
                              subtitle: Text(directoryPath!),
                            )
                          : _paths != null
                              ? Container(
                                  padding:
                                      const EdgeInsets.only(bottom: 30.0),
                                  height:
                                      MediaQuery.of(context).size.height *
                                          0.50,
                                  child: Scrollbar(
                                      child: ListView.separated(
                                    itemCount:
                                        _paths != null && _paths!.isNotEmpty
                                            ? _paths!.length
                                            : 1,
                                    itemBuilder:
                                        (BuildContext context, int index) {
                                      final bool isMultiPath =
                                          _paths != null &&
                                              _paths!.isNotEmpty;
                                      final String name = 'File $index: ' +
                                          (isMultiPath
                                              ? _paths!
                                                  .map((e) => e.name)
                                                  .toList()[index]
                                              : '...');
                                      final path = kIsWeb
                                          ? null
                                          : _paths!
                                              .map((e) => e.path)
                                              .toList()[index]
                                              .toString();

                                      return ListTile(
                                        title: Text(
                                          name,
                                        ),
                                        subtitle: Text(path ?? ''),
                                      );
                                    },
                                    separatorBuilder:
                                        (BuildContext context, int index) =>
                                            const Divider(),
                                  )),
                                )
                              : const SizedBox(),
            ),
          ],
        ),
      ),
    ),
  ),
  );
    }
 }

Solution

  • I write this code inside the build method:

    final directoryPath = ref.watch(directoryPathProvider);
    final userAborted = ref.watch(userAbortedProvider);
    
    Future<void> selectFolder() async {
      String? path = await FilePicker.platform.getDirectoryPath();
      ref.read(directoryPathProvider.notifier).state = path;
      ref.read(userAbortedProvider.notifier).state = path == null;
    }
    

    It's OK now.