Closed IhabMks closed 10 months ago
Hmm. Does your app depend on the latest sqflite_tizen (0.1.2) which includes this patch: https://github.com/flutter-tizen/plugins/commit/fba3848106a122fe8586cbbbf42da11efc90b654?
@swift-kim Yes it does, here's my pubspec:
drift: ^2.8.0
drift_sqflite: ^2.0.1
sqflite_tizen: ^0.1.2
Do you have sample code for reproduction?
Here's a code example:
@DataClassName('EntityA')
class TableA extends Table {
TextColumn get name => text()();
IntColumn get something => integer().nullable()();
@override
Set<Column<Object>>? get primaryKey => {name};
}
@DriftDatabase(
tables: [TableA, TableB, TableC, ...])
class MyDatabase extends _$MyDatabase {
MyDatabase() : super(_openConnection());
// you should bump this number whenever you change or add a table definition.
@override
int get schemaVersion => 1;
}
QueryExecutor _openConnection() {
return SqfliteQueryExecutor.inDatabaseFolder(path: _dbName);
}
class MyProvider extends ChangeNotifier {
final MyDatabase _database = MyDatabase();
int? something = await _database.getSomething();
}
When doing a flutter-tizen run for the first time, it runs fine, but when you do for example changes that needs a reset instead of a hot-reload, the error pops up.
I modified the drift example app slightly to make it dependent on drift_sqflite
(by replacing impl.connect()
with a SqfliteQueryExecutor
), but I'm getting a different error when trying to relaunch the app after installing.
flutter: DatabaseException(trigger todos_insert already exists (code 1))
flutter: #0 wrapDatabaseException (package:sqflite/src/exception_impl.dart:11:7)
flutter: <asynchronous suspension>
flutter: #1 BasicLock.synchronized (package:synchronized/src/basic_lock.dart:33:16)
flutter: <asynchronous suspension>
flutter: #2 SqfliteDatabaseMixin.txnSynchronized (package:sqflite_common/src/database_mixin.dart:490:14)
flutter: <asynchronous suspension>
flutter: #3 Migrator.create (package:drift/src/runtime/query_builder/migration.dart:86:7)
flutter: <asynchronous suspension>
flutter: #4 Migrator.createAll (package:drift/src/runtime/query_builder/migration.dart:76:7)
flutter: <asynchronous suspension>
flutter: #5 GeneratedDatabase.beforeOpen.<anonymous closure> (package:drift/src/runtime/api/db_base.dart:126:9)
flutter: <asynchronous suspension>
flutter: #6 DelegatedDatabase._runMigrations (package:drift/src/runtime/executor/helpers/engines.dart:458:5)
flutter: <asynchronous suspension>
flutter: #7 DelegatedDatabase.ensureOpen.<anonymous closure> (package:drift/src/runtime/executor/helpers/engines.dart:426:7)
flutter: <asynchronous suspension>
flutter: #8 NonNullableCancellationExtension.resultOrNullIfCancelled (package:drift/src/runtime/cancellation_zone.dart:62:24)
flutter: <asynchronous suspension>
flutter: #9 QueryStream.fetchAndEmitData (package:drift/src/runtime/executor/stream_queries.dart:313:20)
flutter: <asynchronous suspension>
I have no idea what is causing the error since I'm not familiar with the drift
library, but anyway, according to the stack trace, the sqflite
plugin was loaded correctly (no "databaseFactory not initialized" error). If you still get the "databaseFactory not initialized" error even after updating sqflite_tizen
to 0.1.2, consider removing the drift_sqflite
dependency itself from your app. As far as I understand (from its README), you don't need the dependency to use the drift
package.
All you need to do is to add a path_provider_tizen
dependency to your app
dependencies:
path_provider_tizen: ^2.1.0
and add the following code to main()
(before calling runApp()
).
open.overrideFor(OperatingSystem.linux, () {
return DynamicLibrary.open('/usr/share/dotnet.tizen/lib/libsqlite3.so');
});
Make sure not to use NativeDatabase.createBackgroundConnection()
(which implicitly spawns an isolate) to open a database connection. Instead, use sqlite3.open()
.
// DON'T:
return NativeDatabase.createBackgroundConnection(await databaseFile);
// DO:
return DatabaseConnection(NativeDatabase.opened(sqlite3.open((await databaseFile).path)));
Reference: https://github.com/flutter-tizen/plugins/issues/277#issuecomment-992126520
Hi, @swift-kim I tried your solution, it works, but this time, upon restarting the app, i'm getting an error related to a specefic method : "getApplicationDocumentsDirectory", which i tried to avoid before.
Packages used: path_provider: ^2.0.7 path_provider_tizen: ^2.1.0
Here's the error:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)
#0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:313:7)
<asynchronous suspension>
#1 getApplicationDocumentsDirectory (package:path_provider/path_provider.dart:120:24)
<asynchronous suspension>
#2 _openConnection.<anonymous closure> (package:tizen_poke/database/database.dart:197:22)
<asynchronous suspension>
#3 LazyDatabase._awaitOpened.<anonymous closure> (package:drift/src/utils/lazy_database.dart:47:32)
<asynchronous suspension>
Could you try explicitly calling getApplicationDocumentsDirectory()
from your app code to see if the path_provider
plugin works?
Note that path_provider_tizen
doesn't work in secondary (non-root) isolates by default so make sure all the code is run on the root isolate.
@swift-kim I did like you asked:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final dbFolder = await getApplicationDocumentsDirectory();
open.overrideFor(OperatingSystem.linux, () {
return DynamicLibrary.open('/usr/share/dotnet.tizen/lib/libsqlite3.so');
});
runApp(ChangeNotifierProvider(
create: (context) => MyProvider(dbFolder),
child: MaterialApp(...)
First application start works fine, but after a restart, still got the same error:
[E] [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method getApplicationDocumentsDirectory on channel plugins.flutter.io/path_provider)
#0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:313:7)
<asynchronous suspension>
#1 getApplicationDocumentsDirectory (package:path_provider/path_provider.dart:120:24)
<asynchronous suspension>
#2 main (package:tizen_poke/main.dart:35:20)
<asynchronous suspension>
Well, I can't reproduce the error, and I can't guess what has gone wrong. You should have the file tizen/flutter/generated_main.dart
in your project, and it should have a plugin registrant entrypoint function which calls PathProviderPlugin.register()
. You will get the error if this function is not called on app startup. The code is already compiled into your app package so it shouldn't matter if it's a first-time launch or a restart.
A simple workaround is to call the function directly in your app code (maybe in main()
),
import 'package:path_provider_tizen/path_provider_tizen.dart';
PathProviderPlugin.register();
but, if possible, I'd like to know what the actual cause of the bug is so that we can fix it.
@swift-kim I just tried calling it from the main method, and it works fine:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
PathProviderPlugin.register();
final dbFolder = await getApplicationDocumentsDirectory();
open.overrideFor(OperatingSystem.linux, () {
return DynamicLibrary.open('/usr/share/dotnet.tizen/lib/libsqlite3.so');
});
...
But as you said, that part of the code is already compiled into the app package, so it wouldn't need to be called again after a restart as it already did the first time.
I'll keep trying different approaches, and it see what the actual cause is.
Please let us know if the problem still persists.
So i'm using drift_sqflite, which uses sqflite's SqfliteQueryExecutor, and the rest is pretty much similar as to using the drift library. Starting the application for the first time, works just fine even when doing a hot-restart, but when doing a proper restart i got the below error, and i'm obliged to exit and do another flutter-tizen run.
Error: