widget_hydrator

Creator: coderz1093

Last updated:

0 purchases

TODO
Add to Cart

Description:

widget hydrator

Widget Hydrator 🌊 #




🚧 Under Active Development 🚧 #
Widget Hydrator is a powerful Flutter package that revolutionizes state management by providing an
easy and flexible way to persist and restore the state of your StatefulWidgets between app restarts.
By using a single mixin, you can add robust state persistence to your widgets with minimal effort,
enhancing user experience and simplifying development.
📚 Table of Contents #

Key Features
Installation
Basic Usage
Advanced Features

Configuration
State Snapshots
Undo/Redo Functionality
Selective Persistence
Custom Serialization
Performance Metrics
State Migration


Best Practices
Common Pitfalls and Solutions
Full Example: Task List Application
To-Do List
Contributing
License
Contact and Support

🌟 Key Features #
Widget Hydrator offers a comprehensive suite of features to enhance your Flutter app's state
management:

✅ Automatic State Persistence: Seamlessly save and restore widget state across app restarts.
✅ Compression Support: Optimize storage usage with built-in data compression.
❌ Encryption Capabilities: Secure sensitive state data with encryption.
✅ In-memory Caching: Improve performance with intelligent caching mechanisms.
✅ Undo/Redo Functionality: Easily implement undo and redo features in your app.
✅ State Migration Support: Smoothly handle state structure changes between app versions.
✅ Selective Persistence: Choose specific parts of your state to persist.
✅ State Snapshots: Create and restore named snapshots of your app's state.
✅ Performance Metrics: Monitor and optimize hydration and persistence operations.
✅ Custom Serialization: Handle complex objects with custom serialization logic.
✅ Flexible Configuration: Tailor the hydration process to your app's needs.

đŸ“Ļ Installation #
To use Widget Hydrator in your Flutter project, add it to your pubspec.yaml:
dependencies:
widget_hydrator: ^0.0.3
copied to clipboard
Then run:
flutter pub get
copied to clipboard
🚀 Basic Usage #

Import the package in your Dart file:

import 'package:widget_hydrator/widget_hydrator.dart';
copied to clipboard

Add the UltimateHydrationMixin to your StatefulWidget's State class:

class _MyWidgetState extends State<MyWidget> with UltimateHydrationMixin {
String _myStateVariable = '';

@override
void initState() {
super.initState();
_initializeHydration();
}

Future<void> _initializeHydration() async {
await initializeHydration(HydrationConfig(
// useCompression: true,
// enableEncryption: true,
// encryptionKey: 'your-secret-key',
));
await ensureHydrated();
}

@override
Map<String, dynamic> persistToJson() {
return {
'myStateVariable': _myStateVariable,
};
}

@override
void hydrateFromJson(Map<String, dynamic> json) {
_myStateVariable = json['myStateVariable'] as String? ?? '';
}

@override
void initializeDefaultState() {
_myStateVariable = 'Default Value';
}

@override
Widget build(BuildContext context) {
return FutureBuilder(
future: ensureHydrated(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(_myStateVariable);
} else {
return CircularProgressIndicator();
}
},
);
}
}
copied to clipboard
🛠 Advanced Features #
Configuration #
Widget Hydrator offers flexible configuration options to tailor its behavior to your app's needs:

HydrationConfig config = HydrationConfig(
// useCompression: true,
// enableEncryption: true,
// encryptionKey: 'your-secret-key',
// version: 1,
// autoSaveInterval: Duration(minutes: 5),
stateExpirationDuration: Duration(days: 7),
// maxRetries: 3,
// debounceDuration: Duration(milliseconds: 300),
);

await initializeHydration(config);
copied to clipboard
📸 State Snapshots #
State snapshots allow you to save and restore specific points in your app's state:
// Create a snapshot
await createSnapshot
('before_important_change
'
);

// Restore a snapshot
await restoreSnapshot('before_important_change');

// Get list of snapshots
List<String> snapshots = await getSnapshots();

// Get snapshot details
Map<String, dynamic> details = await getSnapshotDetails('snapshot_name');

// Delete a snapshot
await deleteSnapshot('old_snapshot');
copied to clipboard
↩ī¸ Undo/Redo Functionality #
Implement undo and redo functionality with ease:
void undoLastAction() {
undo();
// Additional logic if needed
}

void redoLastUndo() {
redo();
// Additional logic if needed
}
copied to clipboard
đŸŽ¯ Selective Persistence #
Choose specific parts of your state to persist:
await persistSelectedKeys
(['user', 'preferences']);
copied to clipboard
🔧 Custom Serialization #
Handle complex objects with custom serialization:
setCustomSerializer
(
(obj) => (obj as ComplexObject).toJson(),
(json) => ComplexObject.fromJson(json as Map<String, dynamic>)
);
copied to clipboard
📊 Performance Metrics #
Monitor the performance of hydration and persistence operations:

Map<String, int> metrics = getPerformanceMetrics();
print
('Hydration took
${metrics['hydrationDuration']}ms');
print('Persistence took ${metrics['persistDuration']
}
ms
'
);
copied to clipboard
🔄 State Migration #
Handle changes in your state structure between app versions:
@override
Future<Map<String, dynamic>> migrateState(Map<String, dynamic> oldState) async {
if (oldState['version'] == 1) {
// Migrate from version 1 to version 2
oldState['newField'] = 'default value';
oldState['version'] = 2;
}
return oldState;
}
copied to clipboard
🌐 Web Configuration #
To ensure that the pako.js library is always included when your Flutter web application is loaded,
add the following script tag to your index.html file located in the web directory of your
Flutter project:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Widget Hydrator</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js"></script>
<!-- Other head elements -->
</head>
<body>
<script src="main.dart.js"></script>
</body>
</html>

copied to clipboard
💡 Best Practices #
To make the most of Widget Hydrator, follow these best practices:


Initialize Early: Call initializeHydration() in your widget's initState() method to
ensure hydration is ready when needed.


Use FutureBuilder: Wrap your widget's content in a FutureBuilder with ensureHydrated() to
handle the asynchronous nature of hydration.


Keep It Simple: Only persist essential state that needs to survive app restarts. Avoid
persisting large amounts of data that can be easily recreated or fetched.


Handle Errors Gracefully: Implement error handling in hydrateFromJson() to deal with
potential issues in the persisted data.


Use Encryption for Sensitive Data: Enable encryption when dealing with user-specific or
sensitive information.


Regularly Clean Up: Implement a mechanism to clear old or unnecessary persisted states to
manage storage efficiently.


Test Thoroughly: Ensure your app works correctly with both fresh installs and updates,
testing various scenarios of state persistence and restoration.


đŸšĢ Common Pitfalls and Solutions #


Persisting Too Much Data:

Problem: Slow performance due to persisting large amounts of data.
Solution: Only persist essential state, use selective persistence for large datasets.



Inconsistent State After Updates:

Problem: App crashes or behaves unexpectedly after an update.
Solution: Implement proper state migration logic in the migrateState() method.



Encryption Key Management:

Problem: Lost or compromised encryption keys.
Solution: Use secure key storage solutions and implement key rotation mechanisms.



Performance Issues:

Problem: Slow app startup due to hydration.
Solution: Use the in-memory cache, optimize the amount of persisted data, and consider
asynchronous loading patterns.



📱 Full Example: Task List Application #
Here's a more comprehensive example of using Widget Hydrator in a task list application:
import 'package:flutter/material.dart';
import 'package:widget_hydrator/widget_hydrator.dart';

class Task {
final String id;
String title;
bool isCompleted;

Task({required this.id, required this.title, this.isCompleted = false});

Map<String, dynamic> toJson() =>
{
'id': id,
'title': title,
'isCompleted': isCompleted,
};

factory Task.fromJson(Map<String, dynamic> json) =>
Task(
id: json['id'],
title: json['title'],
isCompleted: json['isCompleted'],
);
}

class TaskListScreen extends StatefulWidget {
@override
_TaskListScreenState createState() => _TaskListScreenState();
}

class _TaskListScreenState extends State<TaskListScreen> with UltimateHydrationMixin {
List<Task> _tasks = [];

@override
void initState() {
super.initState();
_initializeAndHydrate();
}

Future<void> _initializeAndHydrate() async {
await initializeHydration(HydrationConfig(
// useCompression: false,
// enableEncryption: true,
// encryptionKey: 'bXktc2VjcmV0LWtleS0xMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTA=', // 256-bit Base64 encoded key
stateExpirationDuration: const Duration(days: 7),
));
await _loadTasks();
}

Future<void> _loadTasks() async {
await ensureHydrated();
setState(() {});
}

@override
Map<String, dynamic> persistToJson() {
return {
'tasks': _tasks.map((task) => task.toJson()).toList(),
};
}

@override
void hydrateFromJson(Map<String, dynamic> json) {
final taskList = json['tasks'] as List<dynamic>?;
if (taskList != null) {
_tasks = taskList.map((taskJson) => Task.fromJson(taskJson)).toList();
}
}

@override
void initializeDefaultState() {
_tasks = [];
}

void _addTask(String title) {
setState(() {
_tasks.add(Task(id: DateTime.now().toString(), title: title));
});
}

void _toggleTask(String id) {
setState(() {
final task = _tasks.firstWhere((task) => task.id == id);
task.isCompleted = !task.isCompleted;
});
}

void _deleteTask(String id) {
setState(() {
_tasks.removeWhere((task) => task.id == id);
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Task List')),
body: FutureBuilder(
future: ensureHydrated(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
itemCount: _tasks.length,
itemBuilder: (context, index) {
final task = _tasks[index];
return ListTile(
title: Text(task.title),
leading: Checkbox(
value: task.isCompleted,
onChanged: (_) => _toggleTask(task.id),
),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteTask(task.id),
),
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showDialog(
context: context,
builder: (context) {
String newTaskTitle = '';
return AlertDialog(
title: Text('Add New Task'),
content: TextField(
autofocus: true,
onChanged: (value) => newTaskTitle = value,
),
actions: [
TextButton(
child: Text('Cancel'),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: Text('Add'),
onPressed: () {
if (newTaskTitle.isNotEmpty) {
_addTask(newTaskTitle);
Navigator.pop(context);
}
},
),
],
);
},
);
},
),
);
}
}
copied to clipboard
This example demonstrates a fully functional task list application using Widget Hydrator for state
persistence.
📝 To-Do List #

❌ Implement more comprehensive error handling and recovery mechanisms
❌ Add support for custom storage backends (e.g., SQLite, Hive)
❌ Implement a plugin system for extending functionality
❌ Create video tutorials and interactive documentation
❌ Develop a suite of automated tests for various usage scenarios
❌ Optimize performance for extremely large state objects
❌ Implement a web interface for managing persisted states during development
❌ Add support for remote state synchronization
❌ Develop analytics tools for monitoring state changes over time

🤝 Contributing #
We welcome contributions to the Widget Hydrator project! Here's how you can help:

Fork the repository
Create your feature branch (git checkout -b feature/AmazingFeature)
Commit your changes (git commit -m 'Add some AmazingFeature')
Push to the branch (git push origin feature/AmazingFeature)
Open a Pull Request

Please read CONTRIBUTING.md for details on our code of conduct and the process
for submitting pull requests.
📄 License #
This project is licensed under the MIT License - see the LICENSE.md file for details.
👨‍đŸ’ģ Contact and Support #

Author: Samuel Ssekizinvu
GitHub: @samuelkchris
Twitter: @samuelkchris

If you have any questions, suggestions, or feedback, feel free to reach out. We'd love to hear from
you!
🙏 Acknowledgements #
Special thanks to Luke Pighetti for his ideas and inspiration that
led to the creation of Widget Hydrator.
copied to clipboard

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files In This Product:

Customer Reviews

There are no reviews.