I am trying to fetch some data from the internet, store it to my sqlite database and display it on the screen using a ListView.
When I fetch the data for the first time everything works fine and I am able to see the data on the screen, the data is also inserted in the sqlite database, but when I reopen the app I get an error saying
flutter: The following NoSuchMethodError was thrown building StreamBuilder<StudentModel>(dirty, state:
flutter: _StreamBuilderBaseState<StudentModel, AsyncSnapshot<StudentModel>>#3f888):
flutter: The getter 'studentData' was called on null.
flutter: Receiver: null
flutter: Tried calling: studentData
Here is my model class
class StudentModel {
int status;
String msg;
StudentModelData studentModelData;
StudentModel({this.status, this.msg, this.studentModelData});
StudentModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['msg'];
studentModelData = json['data'] != null ? new StudentModelData.fromJson(json['data']) : null;
}
StudentModel.fromDb(Map<String, dynamic> parsedJson) {
status = parsedJson['status'];
msg = parsedJson['msg'];
studentModelData = parsedJson['data'] != null ? new StudentModelData.fromJson(parsedJson['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['msg'] = this.msg;
if (this.studentModelData != null) {
data['data'] = this.studentModelData.toJson();
}
return data;
}
}
class StudentModelData {
int lastIndex;
List<StudentData> studentData;
StudentModelData({this.lastIndex, this.studentData});
StudentModelData.fromJson(Map<String, dynamic> json) {
lastIndex = json['lastIndex'];
if (json['studentData'] != null) {
studentData = new List<StudentData>();
json['studentData'].forEach((v) {
studentData.add(new StudentData.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['lastIndex'] = this.lastIndex;
if (this.studentData != null) {
data['studentData'] = this.studentData.map((v) => v.toJson()).toList();
}
return data;
}
}
class StudentData {
String studentId;
String studName;
String studProfilepic;
String studentEmail;
String studentMobile;
String courseName;
String classCode;
int minAvg;
int avg;
StudentData(
{this.studentId,
this.studName,
this.studProfilepic,
this.studentEmail,
this.studentMobile,
this.courseName,
this.classCode,
this.minAvg,
this.avg});
StudentData.fromJson(Map<String, dynamic> json) {
studentId = json['student_id'];
studName = json['stud_name'];
studProfilepic = json['stud_profilepic'];
studentEmail = json['student_email'];
studentMobile = json['student_mobile'];
courseName = json['course_name'];
classCode = json['class_code'];
minAvg = json['minAvg'];
avg = json['avg'];
}
StudentData.fromDb(Map<String, dynamic> parsedJson){
studentId = parsedJson['student_id'];
studName = parsedJson['stud_name'];
studProfilepic = parsedJson['stud_profilepic'];
studentEmail = parsedJson['student_email'];
studentMobile = parsedJson['student_mobile'];
courseName = parsedJson['course_name'];
classCode = parsedJson['class_code'];
minAvg = parsedJson['minAvg'];
avg = parsedJson['avg'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['student_id'] = this.studentId;
data['stud_name'] = this.studName;
data['stud_profilepic'] = this.studProfilepic;
data['student_email'] = this.studentEmail;
data['student_mobile'] = this.studentMobile;
data['course_name'] = this.courseName;
data['class_code'] = this.classCode;
data['minAvg'] = this.minAvg;
data['avg'] = this.avg;
return data;
}
}
Following is my repository class
class StudentDbProvider implements Source, Cache {
Database db;
void init() async {
print("database initialized");
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, "students.db");
db = await openDatabase(path, version: 1,
onCreate: (Database newDb, int version) {
newDb.execute("""
CREATE TABLE STUDENTS(
id INTEGER PRIMARY KEY,
student_id TEXT,
stud_name TEXT,
stud_profilepic TEXT,
student_email TEXT,
student_mobile TEXT,
course_name TEXT,
class_code TEXT,
minAvg TEXT,
avg TEXT
)
""");
});
}
#override
Future<int> clear() {
return db.delete("STUDENTS");
}
#override
Future<StudentModel> fetchStudents(String disciplineId, String schoolId,
String year_id, String lastIndex) async {
print("PritishSawant${db==null}");
final maps =
await db.query("STUDENTS");
if (maps.length > 0) {
return StudentModel.fromDb(maps.first);
}
return null;
}
#override
Future<int> addStudent(StudentData studentData) {
return db.insert("STUDENTS", studentData.toJson(),
conflictAlgorithm: ConflictAlgorithm.ignore);
}
}
final studentDbProvider = StudentDbProvider();
Following is my bloc class
class StudentsBloc {
final _repository = Repository();
final _students = PublishSubject<StudentModel>();
Observable<StudentModel> get students => _students.stream;
fetchStudents(String disciplineId,String schoolId,String year_id,String lastIndex) async {
await studentDbProvider.init();
final student = await _repository.fetchStudents(disciplineId, schoolId, year_id, lastIndex);
_students.sink.add(student);
}
clearCache(){
return _repository.clearCache();
}
dispose(){
_students.close();
}
}
As far as I can understand the error must be occurring due to improper database initialisation but when I did the first network request everything was working fine and I did not get any error in the console and the database was also initialised. I am not able to understand why the error is occurring for the second time onwards?
I suppose you are calling snapshot.data.studentData in some part of your code.
On a stream builder, I tend to first do a null check
if (snapshot.data != null) {
// your code here
}
And then proceed to verify the data, else you can use a getter on a null data provided by the StreamBuilder
You should check snapshot!=null && snapshot.hasError to ensure your data is actually returned
if (snapshot!=null && !snapshot.hasError) {
// your code here
}
Related
Why the getCurrencyFromAPI function returns Intance of currency instead of the value itself. Is there some thing wrong with my model class?
This is the function
import 'dart:convert';
import 'package:app_bloc/data/models/currency.dart';
import 'package:http/http.dart' as http;
import 'package:app_bloc/constants/api_urls.dart';
class Repository {
Future<dynamic> getCurrencyFromAPI() async {
final res = await http.get(Uri.parse(coinbaseURL));
if (res.statusCode == 200) {
final resData = jsonDecode(res.body);
final data = resData['data'] as List;
List<Currency> list = [];
for (var e in data) {
final a = Currency.fromJson(e);
list.add(a);
}
print(list);
} else {
throw Exception('Error fetching data from API');
}
}
}
void main(List<String> args) {
Repository repo = Repository();
repo.getCurrencyFromAPI();
}
this is the model class
class Currency {
String id;
String name;
String minSize;
Currency({required this.id, required this.name, required this.minSize});
factory Currency.fromJson(Map<String, dynamic> data) {
final id = data['id'] as String;
final name = data['name'] as String;
final minSize = data['min_size'] as String;
return Currency(id: id, name: name, minSize: minSize);
}
}
Your Currency class does not have a toString method. That means it inherits the default from Object which returns Instance of 'Currency'.
When you print the List<Currency> it calls toString on every element to get a string representation. So, that's what you see. It is a Currency object.
Try adding:
String toString() => "Currency(id: $id, name: $name, minSize: $minSize)";
to you Currency class and see if it makes a difference.
Currency currencyModelFromJson(String str) => Currency.fromJson(json.decode(str));
class Currency {
String id;
String name;
String minSize;
Currency({required this.id, required this.name, required this.minSize});
factory Currency.fromJson(Map<String, dynamic> data) {
final id = data['id'] as String;
final name = data['name'] as String;
final minSize = data['min_size'] as String;
return Currency(id: id, name: name, minSize: minSize);
}
}
Then do this :
class Repository {
Future<dynamic> getCurrencyFromAPI() async {
final res = await http.get(Uri.parse(coinbaseURL));
if (res.statusCode == 200) {
final resData = jsonDecode(res.body);
final data = resData['data'] as List;
List<Currency> list = [];
for (var e in data) {
final a = currencyModelFromJson(e); // change here
list.add(a);
}
print(list);
} else {
throw Exception('Error fetching data from API');
}
}
}
I´m having problems with sqflite in Flutter.
Normal inserts work just fine... but as soon as I insert a value, which is the id I get from inserting int into the first table, I get a syntax error near ")".
This is the error I get:
flutter: error DatabaseException(Error Domain=FMDatabase Code=1 "near
")": syntax error" UserInfo={NSLocalizedDescription=near ")": syntax
error}) sql 'CREATE TABLE pageM (id INTEGER PRIMARY KEY,caardId
INTEGER,title INTEGER,content TEXT,)' args []} during open, closing...
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception:
DatabaseException(Error Domain=FMDatabase Code=1 "near ")": syntax
error" UserInfo={NSLocalizedDescription=near ")": syntax error}) sql
'CREATE TABLE pageM (id INTEGER PRIMARY KEY,caardId INTEGER,title
INTEGER,content TEXT,)' args []}
#0 wrapDatabaseException (package:sqflite/src/exception_impl.dart:11:7)
#1 SqfliteDatabaseFactoryImpl.wrapDatabaseException (package:sqflite/src/factory_impl.dart:78:7)
#2 SqfliteDatabaseMixin.safeInvokeMethod (package:sqflite_common/src/database_mixin.dart:208:15)
#3 SqfliteDatabaseMixin.invokeExecute (package:sqflite_common/src/database_mixin.dart:370:12)
#4 SqfliteDatabaseMixin.txnExecute. (package:sqflite_common/src/database_mixin.dart:362:14)
#5 SqfliteDatabaseMixin.txnSynchronized (package:sqflite_common/src/database_mixin.dart:312:26)
#6 SqfliteDatabaseMixin.txnWriteSynchronized (package:sqflite_common/src/database_mixin.dart:345:<…>
Here my insert:
onPressed: () async {
currentCaard = Caard(topicId: widget.topicId, pageAmount: widget.pageAmount);
print(currentCaard);
currentCaard.id = await DatabaseProviderCaard.db.insert(currentCaard);
currentPage = PageM(caardId: currentCaard.id, title: textControllerTitle.text,content: textControllerContent.text);
DatabaseProviderPage.db.insert(currentPage);
},
and here is my whole db Provider file:
import 'package:caards/model.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:sqflite/sqlite_api.dart';
class DatabaseProviderCaard {
static const String TABLE_CAARD = "caard";
static const String COLUMN_ID = "id";
static const String COLUMN_TOPIC_ID = "topicId";
static const String COLUMN_PAGE_AMOUNT = "pageAmount";
DatabaseProviderCaard._();
static final DatabaseProviderCaard db = DatabaseProviderCaard._();
Database _database;
Future<Database> get database async {
print("caard database getter called");
if (_database != null) {
return _database;
}
_database = await createDatabase();
return _database;
}
Future<Database> createDatabase() async {
String dbPath = await getDatabasesPath();
return await openDatabase(
join(dbPath, 'caardDB.db'),
version: 1,
onCreate: (Database database, int version) async {
print("Creating caard table");
await database.execute(
"CREATE TABLE $TABLE_CAARD ("
"$COLUMN_ID INTEGER PRIMARY KEY,"
"$COLUMN_TOPIC_ID INTEGER,"
"$COLUMN_PAGE_AMOUNT INTEGER"
")",
);
},
);
}
Future<List<Caard>> getCaards() async {
final db = await database;
var caards = await db
.query(TABLE_CAARD, columns: [COLUMN_ID, COLUMN_TOPIC_ID, COLUMN_PAGE_AMOUNT]);
List<Caard> caardList = List<Caard>();
caards.forEach((currentCaard) {
Caard caard = Caard.fromMap(currentCaard);
caardList.add(caard);
});
return caardList;
}
Future<int> insert(Caard caard) async {
final db = await database;
caard.id = await db.insert(TABLE_CAARD, caard.toMap());
return caard.id;
}
Future<int> delete(int id) async {
final db = await database;
return await db.delete(
TABLE_CAARD,
where: "id = ?",
whereArgs: [id],
);
}
Future<int> update(Caard caard) async {
final db = await database;
return await db.update(
TABLE_CAARD,
caard.toMap(),
where: "id = ?",
whereArgs: [caard.id],
);
}
}
class DatabaseProviderPage {
static const String TABLE_PAGE = "page";
static const String COLUMN_ID = "id";
static const String COLUMN_CAARD_ID = "caardId";
static const String COLUMN_TITLE = "title";
static const String COLUMN_CONTENT = "content";
DatabaseProviderPage._();
static final DatabaseProviderPage db = DatabaseProviderPage._();
Database _database;
Future<Database> get database async {
print("page database getter called");
if (_database != null) {
return _database;
}
_database = await createDatabase();
return _database;
}
Future<Database> createDatabase() async {
String dbPath = await getDatabasesPath();
return await openDatabase(
join(dbPath, 'pageDB.db'),
version: 1,
onCreate: (Database database, int version) async {
print("Creating page table");
await database.execute(
"CREATE TABLE $TABLE_PAGE ("
"$COLUMN_ID INTEGER PRIMARY KEY,"
"$COLUMN_CAARD_ID INTEGER,"
"$COLUMN_TITLE INTEGER,"
"$COLUMN_CONTENT TEXT,"
")",
);
},
);
}
Future<List<PageM>> getPages() async {
final db = await database;
var pages = await db
.query(TABLE_PAGE, columns: [COLUMN_ID, COLUMN_CAARD_ID, COLUMN_TITLE, COLUMN_CONTENT]);
List<PageM> pageList = List<PageM>();
pages.forEach((currentPage) {
PageM page = PageM.fromMap(currentPage);
pageList.add(page);
});
return pageList;
}
Future<PageM> insert(PageM pageM) async {
final db = await database;
pageM.id = await db.insert(TABLE_PAGE, pageM.toMap());
return pageM;
}
Future<int> delete(int id) async {
final db = await database;
return await db.delete(
TABLE_PAGE,
where: "id = ?",
whereArgs: [id],
);
}
Future<int> update(PageM page) async {
final db = await database;
return await db.update(
TABLE_PAGE,
page.toMap(),
where: "id = ?",
whereArgs: [page.id],
);
}
}
and here is my Model:
import 'package:caards/database_provider.dart';
class Caard {
int id;
int topicId;
int pageAmount;
Caard({this.id, this.topicId, this.pageAmount});
Map<String, dynamic> toMap() {
var map = <String, dynamic>{
DatabaseProviderCaard.COLUMN_ID: id, //versuch
DatabaseProviderCaard.COLUMN_TOPIC_ID: topicId,
DatabaseProviderCaard.COLUMN_PAGE_AMOUNT: pageAmount
};
if (id != null) {
map[DatabaseProviderCaard.COLUMN_ID] = id;
}
return map;
}
Caard.fromMap(Map<String, dynamic> map) {
id = map[DatabaseProviderCaard.COLUMN_ID];
topicId = map[DatabaseProviderCaard.COLUMN_TOPIC_ID];
pageAmount = map[DatabaseProviderCaard.COLUMN_PAGE_AMOUNT];
}
}
class PageM {
int id;
int caardId;
String title;
String content;
PageM({this.id, this.caardId, this.title, this.content});
Map<String, dynamic> toMap() {
var map = <String, dynamic>{
DatabaseProviderPage.COLUMN_CAARD_ID: caardId,
DatabaseProviderPage.COLUMN_TITLE: title,
DatabaseProviderPage.COLUMN_CONTENT: content
};
if (id != null) {
map[DatabaseProviderPage.COLUMN_ID] = id;
}
return map;
}
PageM.fromMap(Map<String, dynamic> map) {
id = map[DatabaseProviderPage.COLUMN_ID];
caardId = map[DatabaseProviderPage.COLUMN_CAARD_ID];
title = map[DatabaseProviderPage.COLUMN_TITLE];
content = map[DatabaseProviderPage.COLUMN_CONTENT];
}
}
```
You need to syntactically correct the SQL query.
You currently use:
'CREATE TABLE pageM (id INTEGER PRIMARY KEY,caardId INTEGER,title INTEGER,content TEXT,)'
This query has an extra comma in the end, which is not syntactically correct. That is why the DB complains about a syntax error. In fact in the error message of the DB there is the query created using the code, inside which there is a trailing comma ',' before the parenthesis. Change your code so that the query is:
'CREATE TABLE pageM (id INTEGER PRIMARY KEY,caardId INTEGER,title INTEGER,content TEXT)'
You need to change the following part in the DB Provider file.
The error is caused because there is a comma after TEXT in the following part:
await database.execute(
"CREATE TABLE $TABLE_PAGE ("
"$COLUMN_ID INTEGER PRIMARY KEY,"
"$COLUMN_CAARD_ID INTEGER,"
"$COLUMN_TITLE INTEGER,"
"$COLUMN_CONTENT TEXT,"
")",
A correct version would be the following.
await database.execute(
"CREATE TABLE $TABLE_PAGE ("
"$COLUMN_ID INTEGER PRIMARY KEY,"
"$COLUMN_CAARD_ID INTEGER,"
"$COLUMN_TITLE INTEGER,"
"$COLUMN_CONTENT TEXT"
")",
I want to fetch data from the server, then parse json. When they are done, I want to navigate to another view.
void getServerData() async{
WebRequests ws = WebRequests('https://sampleurl');
Map<String, dynamic> map = await ws.getData();
mychamplist = map['mychampionships'];
mychamplist.forEach((f){
mychampionships.add(MyChampionships(
name: f['name'],
id: int.parse(f['id']),
numberOfPlayers: int.parse(f['nofplayers']),
));
});
Navigator
.of(context)
.pushReplacement(new MaterialPageRoute(builder: (BuildContext context) {
return FantasyNbi();
}));
}
It navigates to the FantasyNbi class before the previous code finished.
How could it do in proper way?
I do have a example class for you that you could use:
class API {
static Future getData(String url) {
return http.get('api link' + url);
}
static Future<List<BasicDiskInfo>> fetchAllDisks() async {
final response = await getData('disk');
if (response.statusCode == 200) {
Iterable list = json.decode(response.body);
List<BasicDiskInfo> disks =
list.map((model) => BasicDiskInfo.fromJson(model)).toList();
return disks;
} else {
throw Exception('Failed to load disks');
}
}
static Future<Disk> fetchDisk(int id) async {
final response = await getData('disk/' + id.toString());
if (response.statusCode == 200) {
return Disk.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load disk');
}
}
}
class Disk {
int id;
String name;
String volumeLable;
bool isReady;
String driveType;
String driveFormat;
int totalSize;
int totalFreeSpace;
int availableFreeSpace;
Disk(
{this.id,
this.name,
this.volumeLable,
this.isReady,
this.driveType,
this.driveFormat,
this.totalSize,
this.totalFreeSpace,
this.availableFreeSpace});
factory Disk.fromJson(Map<String, dynamic> json) {
return Disk(
id: json['id'],
name: json['name'],
volumeLable: json['volumeLable'],
isReady: json['isReady'],
driveType: json['driveType'],
driveFormat: json['driveFormat'],
totalSize: json['totalSize'],
totalFreeSpace: json['totalFreeSpace'],
availableFreeSpace: json['availableFreeSpace']);
}
}
And to get the data I can do this:
var data = await API.fetchAllDisks();
// or
API.fetchAllDisks().then((response) => {/* do something */})
I am trying to fetch some data from network and store it in sqlite database. Following is the model class
class StudentModel {
int status;
String msg;
StudentModelData studentModelData;
StudentModel({this.status, this.msg, this.studentModelData});
StudentModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['msg'];
studentModelData = json['data'] != null ? new StudentModelData.fromJson(json['data']) : null;
}
StudentModel.fromDb(Map<String, dynamic> parsedJson) {
status = parsedJson['status'];
msg = parsedJson['msg'];
studentModelData = studentModelData = jsonDecode(json['data']) != null ? new StudentModelData.fromJson(jsonDecode(json['data'])) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['msg'] = this.msg;
if (this.studentModelData != null) {
data['data'] = this.studentModelData.toJson();
}
return data;
}
}
class StudentModelData {
int lastIndex;
List<StudentData> studentData;
StudentModelData({this.lastIndex, this.studentData});
StudentModelData.fromJson(Map<String, dynamic> json) {
lastIndex = json['lastIndex'];
if (json['studentData'] != null) {
studentData = new List<StudentData>();
json['studentData'].forEach((v) {
studentData.add(new StudentData.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['lastIndex'] = this.lastIndex;
if (this.studentData != null) {
data['studentData'] = this.studentData.map((v) => v.toJson()).toList();
}
return data;
}
}
class StudentData {
String studentId;
String studName;
String studProfilepic;
String studentEmail;
String studentMobile;
String courseName;
String classCode;
int minAvg;
int avg;
StudentData(
{this.studentId,
this.studName,
this.studProfilepic,
this.studentEmail,
this.studentMobile,
this.courseName,
this.classCode,
this.minAvg,
this.avg});
StudentData.fromJson(Map<String, dynamic> json) {
studentId = json['student_id'];
studName = json['stud_name'];
studProfilepic = json['stud_profilepic'];
studentEmail = json['student_email'];
studentMobile = json['student_mobile'];
courseName = json['course_name'];
classCode = json['class_code'];
minAvg = json['minAvg'];
avg = json['avg'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['student_id'] = this.studentId;
data['stud_name'] = this.studName;
data['stud_profilepic'] = this.studProfilepic;
data['student_email'] = this.studentEmail;
data['student_mobile'] = this.studentMobile;
data['course_name'] = this.courseName;
data['class_code'] = this.classCode;
data['minAvg'] = this.minAvg;
data['avg'] = this.avg;
return data;
}
}
And my database provider class looks like following
class StudentDbProvider implements Source, Cache {
Database db;
StudentDbProvider() {
init();
}
void init() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, "students.db");
db = await openDatabase(path, version: 1,
onCreate: (Database newDb, int version) {
newDb.execute("""
CREATE TABLE STUDENTS(
id INTEGER PRIMARY KEY,
status INTEGER,
msg TEXT,
data BLOB
)
""");
});
}
#override
Future<int> clear() {
return db.delete("STUDENTS");
}
#override
Future<StudentModel> fetchStudents(String disciplineId, String schoolId,
String year_id, String lastIndex) async {
final maps =
await db.query("STUDENTS");
if (maps.length > 0) {
return StudentModel.fromDb(maps.first);
}
return null;
}
#override
Future<int> addStudent(StudentModel studentModel) {
return db.insert("STUDENTS", studentModel.toJson(),conflictAlgorithm: ConflictAlgorithm.ignore);
}
}
final studentDbProvider = StudentDbProvider();
Whenever I tried to fetch the data and stored in the database, I get the following error in the console
NoSuchMethodError: The method 'query' was called on null.
Receiver: null
Tried calling: query("STUDENTS")
#0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
The data gets added to the database but I am not able to query the data from the database.
Reducing at minimum your example, this throws the exception The method 'query' was called on null
because fetch is executed before db is properly initialized:
class Database {
Future<int> query() {
return Future.value(1);
}
}
const oneSecond = Duration(seconds: 1);
class Provider {
Database db;
Provider() {
init();
}
void init() async {
db = await Future.delayed(oneSecond, () => Database());
}
Future<int> fetch() {
return db.query();
}
}
main() async {
var provider = Provider();
await provider.fetch();
}
The problem resides in calling an async method inside a constructor, see also:
Calling an async method from component constructor in Dart
This works:
class Database {
Future<int> query() {
return Future.value(1);
}
}
const oneSecond = Duration(seconds: 1);
class Provider {
Database db;
Provider() {
//init();
}
void init() async {
db = await Future.delayed(oneSecond, () => Database());
}
Future<int> fetch() {
return db.query();
}
}
main() async {
var provider = Provider();
await provider.init();
await provider.fetch();
}
Please note that init must be awaited, otherwise you will catch the same The method 'query' was called on null.
the problem is the init must be awaited. here what I did to fix it
_onCreate(Database db, int version) async {
await db.execute('CREATE TABLE ... <YOUR QUERY CREATION GOES HERE>');
}
Future<Database> getDatabaseInstance() async {
final String databasesPath = await getDatabasesPath();
final String path = join(databasesPath, '<YOUR DB NAME>');
return await openDatabase(path, version: 1, onCreate: _onCreate);
}
Future<int> save(Contact contact) {
return getDatabaseInstance().then((db) {
final Map<String, dynamic> contactMap = Map();
contactMap['name'] = contact.name;
contactMap['account_number'] = contact.accountNumber;
return db.insert('contacts', contactMap);
});
}
The SQFlite page gives a good example about it and helps a lot.
https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_db.md
I am calling service using ConnectionRequest class and if i'm getting result in English i'm able to display it but if i'm getting response in Hindi at that time getting as question marks(?) instead of Hindi text. and i'm using Devanagari Font to show the hindi text. is there any solution for this?
here is the code for how we are requesting?
adding parameters using Map like below.
Map<String, Object> map = new HashMap<String, Object>();
map.add("Key","Value");
map.add("Key1","Value1");
etc..
then passing this map object to requestService method.
private static Map<String, Object> requestService(Map<String, Object> data) {
Connection connection = null;
Dialog progress = new InfiniteProgress().showInifiniteBlocking();
try {
connection = new Connection(data);
NetworkManager networkManager = NetworkManager.getInstance();
networkManager.addToQueueAndWait(connection);
networkManager.setTimeout(600000);
if(connection.getResponseData() == null) {
return null;
}
} finally {
progress.dispose();
}
JSONParser jp = new JSONParser();
try {
Map<String, Object> result = jp.parseJSON(new InputStreamReader(new ByteArrayInputStream(connection.getResponseData()), "UTF-8"));
return result;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
Connection Class:
private static class Connection extends ConnectionRequest {
private final static char escapeS[] = new char[] { '"', '\\', '/', '\b', '\f', '\n', '\r', '\t' };
private final static char escapeR[] = new char[] { '"', '\\', '/', 'b', 'f', 'n', 'r', 't' };
private Map<String, Object> data;
private Connection(Map<String, Object> data) {
this.data = data;
setFailSilently(true);
setPost(true);
setWriteRequest(true);
setContentType("application/json");
setUrl(serverUrl);
}
#Override
protected void buildRequestBody(OutputStream os) throws IOException {
String v = buildJSON(data);
if(shouldWriteUTFAsGetBytes()) {
os.write(v.getBytes("UTF-8"));
} else {
OutputStreamWriter w = new OutputStreamWriter(os, "UTF-8");
w.write(v);
}
}
private static String buildJSON(Map<String, Object> data) {
StringBuilder json = new StringBuilder();
buildJSON(data, json);
return json.toString();
}
#SuppressWarnings("unchecked")
private static void buildJSON(Map<String, Object> data, StringBuilder json) {
json.append('{');
boolean first = true;
Object value;
for(String key: data.keySet()) {
value = data.get(key);
if(value == null) {
continue;
}
if(first) {
first = false;
} else {
json.append(",");
}
json.append('"').append(key).append("\":");
if(value instanceof Map) {
buildJSON((Map<String, Object>) value, json);
} else if(value instanceof Collection) {
buildJSON((Collection<Map<String, Object>>)value, json);
} else {
if(value instanceof Long || value instanceof Integer || value instanceof Double
|| value instanceof Short || value instanceof Float) {
json.append(value);
} else if(value instanceof Boolean) {
json.append((Boolean)value ? "true" : "false");
} else {
json.append('"').append(escape(value)).append('"');
}
}
}
json.append('}');
}
private static void buildJSON(Collection<Map<String, Object>> data, StringBuilder json) {
json.append('[');
boolean first = true;
for(Map<String, Object> e: data) {
if(first) {
first = false;
} else {
json.append(",");
}
buildJSON(e, json);
}
json.append(']');
}
private static String escape(Object any) {
if(any == null) {
return "";
}
String s = any.toString();
if(s == null) {
return "";
}
for(int i = 0; i < escapeS.length; i++) {
s = replace(s, escapeS[i], escapeR[i]);
}
return s;
}
private static String replace(String s, char c, char r) {
int i = s.indexOf(c);
if(i < 0) {
return s;
}
return s.substring(0, i) + "\\" + r + replace(s.substring(i + 1), c, r);
}
}
please guide me to achieve this?
That means the result is encoded in a foreign language encoding and should be read using the correct hindi text encoding.