I want to open a Hive box based on the current logged in user. To do this I open a box on log in with the user’s uid and close all boxes when logging out. The uid is stored inside app preferences for later use.
<code>Future signInWithEmailAndPassword(String email, String password) async {
UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
User? user = result.user;
prefs!.setString(AppConstants.kBoxPreferenceKey, user!.uid);
await Hive.openBox(user.uid);
<code>Future signInWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
User? user = result.user;
prefs!.setString(AppConstants.kBoxPreferenceKey, user!.uid);
await Hive.openBox(user.uid);
return user;
} catch (error) {
print(error.toString());
return null;
}
}
</code>
Future signInWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
User? user = result.user;
prefs!.setString(AppConstants.kBoxPreferenceKey, user!.uid);
await Hive.openBox(user.uid);
return user;
} catch (error) {
print(error.toString());
return null;
}
}
<code>Future signOut() async {
prefs!.remove(AppConstants.kBoxPreferenceKey);
return await _auth.signOut();
<code>Future signOut() async {
prefs!.remove(AppConstants.kBoxPreferenceKey);
await Hive.close();
try {
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
</code>
Future signOut() async {
prefs!.remove(AppConstants.kBoxPreferenceKey);
await Hive.close();
try {
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
After this I have a Change Notifier that handles the local database
<code>class CardsDataBase extends ChangeNotifier {
// This isn't final, ıt's here just to make sure I have the correct box name from prefs before doing anything else
String boxName = prefs!.getString(AppConstants.kBoxPreferenceKey)!;
_myBox = Hive.box(boxName);
void deleteFolder(String folderName) {
String uid = prefs!.getString(AppConstants.kBoxPreferenceKey)!;
_myBox.delete(folderName);
void updateDataBase(String listName, List listContent) {
_myBox = Hive.box(prefs!.getString(AppConstants.kBoxPreferenceKey)!);
_myBox.put(listName, listContent);
<code>class CardsDataBase extends ChangeNotifier {
late Box _myBox;
Box get myBox => _myBox;
CardsDataBase() {
getFolderModels();
// This isn't final, ıt's here just to make sure I have the correct box name from prefs before doing anything else
}
void getFolderModels() {
String boxName = prefs!.getString(AppConstants.kBoxPreferenceKey)!;
_myBox = Hive.box(boxName);
notifyListeners();
}
void deleteFolder(String folderName) {
String uid = prefs!.getString(AppConstants.kBoxPreferenceKey)!;
_myBox = Hive.box(uid);
_myBox.delete(folderName);
notifyListeners();
}
void updateDataBase(String listName, List listContent) {
_myBox = Hive.box(prefs!.getString(AppConstants.kBoxPreferenceKey)!);
_myBox.put(listName, listContent);
notifyListeners();
}
}
</code>
class CardsDataBase extends ChangeNotifier {
late Box _myBox;
Box get myBox => _myBox;
CardsDataBase() {
getFolderModels();
// This isn't final, ıt's here just to make sure I have the correct box name from prefs before doing anything else
}
void getFolderModels() {
String boxName = prefs!.getString(AppConstants.kBoxPreferenceKey)!;
_myBox = Hive.box(boxName);
notifyListeners();
}
void deleteFolder(String folderName) {
String uid = prefs!.getString(AppConstants.kBoxPreferenceKey)!;
_myBox = Hive.box(uid);
_myBox.delete(folderName);
notifyListeners();
}
void updateDataBase(String listName, List listContent) {
_myBox = Hive.box(prefs!.getString(AppConstants.kBoxPreferenceKey)!);
_myBox.put(listName, listContent);
notifyListeners();
}
}
The problem occurs inside the library screen where I show the folders from myBox. It works fine and updates as expected until I log out and log back in with the same or a different account.
<code>class LibraryScreen extends StatefulWidget {...}
class _LibraryScreenState extends State<LibraryScreen> {
Widget build(BuildContext context) {
final provider = Provider.of<CardsDataBase>(context);
Iterable listOfKeysFromBox = provider.myBox.keys; //error: Box has already been closed
List<FolderWidget> folderWidgetsList = listOfKeysFromBox.map((e)=>
FolderWidget(folderName: e, folderLocation: FolderLocation.downloaded, folderContents: provider.myBox.get(e))
List<StatelessWidget> listForDownloadedColumn = [
const Text('Downloaded Folders',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700)),
listForDownloadedColumn.addAll(folderWidgetsList);
<code>class LibraryScreen extends StatefulWidget {...}
class _LibraryScreenState extends State<LibraryScreen> {
@override
Widget build(BuildContext context) {
final provider = Provider.of<CardsDataBase>(context);
Iterable listOfKeysFromBox = provider.myBox.keys; //error: Box has already been closed
List<FolderWidget> folderWidgetsList = listOfKeysFromBox.map((e)=>
FolderWidget(folderName: e, folderLocation: FolderLocation.downloaded, folderContents: provider.myBox.get(e))
).toList();
List<StatelessWidget> listForDownloadedColumn = [
const Text('Downloaded Folders',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700)),
const MyDivider(),
];
listForDownloadedColumn.addAll(folderWidgetsList);
return Scaffold(...)
}
</code>
class LibraryScreen extends StatefulWidget {...}
class _LibraryScreenState extends State<LibraryScreen> {
@override
Widget build(BuildContext context) {
final provider = Provider.of<CardsDataBase>(context);
Iterable listOfKeysFromBox = provider.myBox.keys; //error: Box has already been closed
List<FolderWidget> folderWidgetsList = listOfKeysFromBox.map((e)=>
FolderWidget(folderName: e, folderLocation: FolderLocation.downloaded, folderContents: provider.myBox.get(e))
).toList();
List<StatelessWidget> listForDownloadedColumn = [
const Text('Downloaded Folders',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700)),
const MyDivider(),
];
listForDownloadedColumn.addAll(folderWidgetsList);
return Scaffold(...)
}
I don’t understand why I don’t receive the new box I opened on sign in, when testing the values inside CardsDataBase
I see that they are indeed the correct values and that the _myBox
is the correct box.