Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Use Hivedb with WorkManager #676

Closed
shaadart opened this issue May 26, 2021 · 12 comments
Closed

How to Use Hivedb with WorkManager #676

shaadart opened this issue May 26, 2021 · 12 comments
Labels
question Further information is requested

Comments

@shaadart
Copy link

shaadart commented May 26, 2021

Question
I am Not Able to Run HiveDb with WorkManager, workmanager: ^0.4.0

I am always thankful for the opensource plugin that you have made,
This is very important for all of us developers of flutter to make things work in the background and respect++...
My Issue
In My App,

const String quotesCardname = "quotes";

//var  = ValueNotifier<int>(2);

ValueNotifier<int> totalTodoCount = ValueNotifier(10 -
    (todoBox.length +
        completedBox.length)); //limiting the toodolee count to 10.
const quote = "refreshQuote";

const reset = "simpleTask";
final player = AudioCache(); //Plays Sounds
Box<CompletedTodoModel> completedBox; //For Box

Box quotesBox;


void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  Workmanager.initialize(callbackDispatcher);

   Workmanager.registerPeriodicTask("100", reset,
       frequency: Duration(hours: 24), initialDelay: Duration(seconds: 40));



  


  final document =
      await getApplicationDocumentsDirectory(); // Getting the Path of App Directory
  Hive.init(document.path); //Initialization of Hive in it.

  //Registering Adapters
  Hive.registerAdapter(TodoModelAdapter());
  Hive.registerAdapter(CompletedTodoModelAdapter());

  //Opening Boxes
  await Hive.openBox(weatherBoxname);
  await Hive.openBox<TodoModel>(todoBoxname);
  await Hive.openBox<CompletedTodoModel>(completedtodoBoxname);
  await Hive.openBox(welcomeBoringCardname);
  await Hive.openBox(quotesCardname);
  await Hive.openBox(dailyRemainderBoxName);
  await Hive.openBox(boringcardName);
  await Hive.openBox(settingsName);
  await Hive.openBox(onboardingScreenBoxName);

  runApp(MyApp()); 
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //Configure Splash Screeeen.
    return FutureBuilder(
        future: Future.delayed(Duration(seconds: 3)),
        builder: (context, AsyncSnapshot snapshot) {
          // Show splash screen while waiting for app resources to load:
          if (snapshot.connectionState == ConnectionState.waiting) {
            player.play(
              'sounds/notification_ambient.wav',
              mode: PlayerMode.MEDIA_PLAYER,
              // stayAwake: false,
              // mode: PlayerMode.LOW_LATENCY,
            );

            return MaterialApp(home: Splash(), title: 'Toodolee');
          } else {
//Ghost White: 0xffF6F8FF
//Lemon Glacier :0xffFBFB0E
//Rich Black: 0xff010C13
// Azure: 0xff4785FF

            return AdaptiveTheme(
              light: ThemeData(
                  fontFamily: "WorkSans",
                  brightness: Brightness.light,
                  primaryColor: Color(0xffFBFB0E),
                  accentColor: Color(0xff4785FF),
                  backgroundColor: Color(0xffF6F8FF)),
              dark: ThemeData(
                fontFamily: "WorkSans",
                brightness: Brightness.dark,
                primaryColor: Color(0xff4785FF),
                accentColor: Color(0xffFBFB0E),
              ),
              initial: AdaptiveThemeMode.light,
              builder: (theme, darkTheme) => MaterialApp(
                title: 'Toodolee',
                theme: theme,
                darkTheme: darkTheme,
                home: DefaultedApp(),
              ),
            );
          }
        });
  }
}

class Splash extends StatefulWidget {
  @override
  _SplashState createState() => _SplashState();
}

class _SplashState extends State<Splash> {
  @override
  void initState() {
    // setupWorkManager();
    super.initState();


    quotesBox = Hive.box(quotesCardname);

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.white70,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            FadeInUpBig(
              duration: Duration(milliseconds: 1200),
              child: Center(
                child: Image.asset(
                  "icon/toodoleeicon.png",
                  height: MediaQuery.of(context).size.width / 2,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

...


void callbackDispatcher() {
  Workmanager.executeTask((task, inputData) {
    deleteQuotes();

    return Future.value(true);
  });
}

Future deleteQuotes() async {
  await quotesBox.clear();
}

It is Giving me an Error that .clear() is Called null..
I am Using HiveDB.
I am Using WorkManager
When I am running everything normally, everything is running well and
clearing well, but when I am using work manager it is showing the error,

Version
I am Using Android,
Latest Version of Hive
And WorkManager

@shaadart shaadart added the question Further information is requested label May 26, 2021
@themisir
Copy link
Contributor

themisir commented May 26, 2021

Hive does not works well when running on multiple isolates. I would suggest system APIs like shared preferences or secure storage for storing data that's used on background.

@shaadart
Copy link
Author

So Can i Use, Hive Simultaneously, Because Hive made literally 80% of the Workspace, it will not be healthy for my Application to bear the baggage. and can you explain the above ones @themisir

@themisir
Copy link
Contributor

Dart doesn't support sharing memory between isolates. And hive relies on memory after you've opened the box. Due to that limitation on dart (not being able to share memory) Hive box could be get damaged when both isolates are trying to write to it same time.

What you can do is:

  1. Open the box on main isolate and communicate with it using Send and ReceivePort. I will not explain the whole process since it's not easy to explain it there. Just doing a bit of research might help you on that.
  2. Use something else for shared data. You can use shared_preferences for simple key value type data.
  3. Not doing tasks on background.

@themisir
Copy link
Contributor

Duplicate of #444

@PapyElGringo
Copy link

@themisir What is the issue exactly?
Is it trying to write in the same Hivedb from two different isolates?
Is reading the same hivedb from different isolates an issue two?
Can we write to different hive database from each isolates?

@themisir
Copy link
Contributor

@themisir What is the issue exactly?
Is it trying to write in the same Hivedb from two different isolates?
Is reading the same hivedb from different isolates an issue two?
Can we write to different hive database from each isolates?

Issue is when you open same box on 2 different isolate and make changes isolates can't let each other know that data is changed, so when you write something else on other isolate changes made by first isolate will be overwritten.

@PapyElGringo
Copy link

@themisir I could live with data being overwritten my main issue is that the box become corrupted and then all data is lost do you know which specific scenario cause this?

@themisir
Copy link
Contributor

@themisir I could live with data being overwritten my main issue is that the box become corrupted and then all data is lost do you know which specific scenario cause this?

When multiple un-synced isolates tries to update data on disk they might write different data on same time causing box file to corrupt. Actually I think there's quite low chance of this happening (both writes have to happen at same time), but I can't guarantee, real life use-cases usually far more complex.

Also have you tried upgrading hive to ^2.0.6 which fixed a bug caused hive db to fail crash recovery and make box file corrupted.

@PapyElGringo
Copy link

@themisir thanks for the answers I didn't I'm on 2.0.4 right now but once of my device hivedb corrupted when receiving a new notification from a firebaseMessagingBackgroundHandler that write the content of the notification inside a Hivedb that how I discovered the isolate issues and I don't really know how to handle this properly my app was on the way to be released with this "bomb" inside !

@themisir
Copy link
Contributor

I don't really know how to handle this properly my app was on the way to be released with this "bomb" inside !

Yeah, it kinda sucks we haven't found a way to properly solve this issue. The main "system-level" problem is dart doesn't supports shared memory space. So we can't make sure hive instances to talk with each other. We're currently researching ways to implement a "fix" to this issue (#922).

@PapyElGringo
Copy link

@themisir Yeah I saw it but I don't have proper input for it I was tempted to check on the Isar side but I'm a bit worried about the young age of it and I face trouble to make it work easily with Freezed and Firebase but I'm still experiencing
But thanks you very much for the support

@jpolstre
Copy link

jpolstre commented Apr 7, 2022

@themisir ¿Cuál es exactamente el problema?
¿Está tratando de escribir en el mismo Hivedb desde dos aislamientos diferentes?
¿Leer el mismo hivedb de diferentes aislamientos es un problema dos?
¿Podemos escribir en diferentes bases de datos de colmenas de cada aislado?

El problema es cuando abre el mismo cuadro en 2 aislamientos diferentes y realiza cambios, los aislamientos no pueden informarse entre sí que los datos han cambiado, por lo que cuando escribe algo más en otro aislamiento, los cambios realizados por el primer aislamiento se sobrescribirán.

close the box of the isolates after modifying them (update, create or delete). So :quotesBox.close();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants