How to get data from model class with using SQFlite in Flutter? - flutter

Here I use SqFlite functionality with model class for data store. But problem is that, when I click on button, addData method was called null.
This is my model class.
import 'dart:convert';
DatabaseModel fromJson({String str}) {
final jsonData = json.decode(str);
return DatabaseModel.fromMap(jsonData);
}
String toJson(DatabaseModel databaseModel) {
final dyn = databaseModel.toMap();
return json.encode(dyn);
}
class DatabaseModel {
String id;
String imageUrl;
String title;
String description;
String newsLink;
String createDate;
String category;
String footerTitle;
DatabaseModel(
{this.id,
this.imageUrl,
this.title,
this.description,
this.newsLink,
this.createDate,
this.category,
this.footerTitle});
factory DatabaseModel.fromMap(Map<String, dynamic> json) => DatabaseModel(
id: json['id'],
imageUrl: json['imageUrl'],
title: json['title'],
description: json['description'],
newsLink: json['newsLink'],
createDate: json['createDate'],
category: json['category'],
footerTitle: json['footerTitle']);
Map<String, dynamic> toMap() => {
'id': id,
'imageUrl': imageUrl,
'title': title,
'description': description,
'newsLink': newsLink,
'createDate': createDate,
'category': category,
'footerTitle': footerTitle
};
}
Now, I display my database class which I use for Add, Delete, and Get data. In this class I use Model class because I want to display my data in Bookmark class.
import 'dart:io';
import 'package:news_app/src/model/bookmark_db_provider.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseProvider {
// DatabaseProvider._();
// static final DatabaseProvider db = DatabaseProvider._();
Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await getDatabaseInstance();
return _database;
}
Future<Database> getDatabaseInstance() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = join(directory.path, 'bookmark.db');
return await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
await db.execute('create table Bookmark ('
'id integer primary key autoincrement,'
'imageUrl text,'
'title text,'
'description text,'
'newsLink text,'
'createDate text,'
'category text,'
'footerTitle text'
')');
});
}
addToDatabase(DatabaseModel databaseModel) async {
final db = await database;
var raw = await db.insert('Bookmark', databaseModel.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace);
return raw;
}
updateDatabase(DatabaseModel databaseModel) async {
final db = await database;
var response = await db.update('Bookmark', databaseModel.toMap(),
where: 'id = ?', whereArgs: [databaseModel.id]);
return response;
}
Future<DatabaseModel> getDatabaseModelWithId(int id) async {
final db = await database;
var response = await db.query('Bookmark', where: 'id = ?', whereArgs: [id]);
return response.isNotEmpty ? DatabaseModel.fromMap(response.first) : null;
}
Future<List<DatabaseModel>> getAllData() async {
final db = await database;
var response = await db.query('Bookmark');
List<DatabaseModel> list =
response.map((c) => DatabaseModel.fromMap(c)).toList();
return list;
}
deleteDatabase(int id) async {
final db = await database;
return db.delete('Bookmark', where: 'id = ?', whereArgs: [id]);
}
deleteAllDatabase() async {
final db = await database;
db.delete('Bookmark');
}
}
Here I display my BookMark class. This class I use for display data for user.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:news_app/src/model/bookmark_db_provider.dart';
import 'package:news_app/src/screens/home.dart';
import 'package:news_app/src/utils/database.dart';
class BookMark extends StatefulWidget {
#override
_BookMarkState createState() => _BookMarkState();
}
class _BookMarkState extends State<BookMark> {
DatabaseProvider databaseProvider;
#override
void initState() {
super.initState();
databaseProvider = DatabaseProvider();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage())),
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
appBar: AppBar(
backgroundColor: Theme.of(context).appBarTheme.color,
elevation: 0,
centerTitle: true,
title: Text(
'BookMark News',
style: TextStyle(fontSize: 23, fontWeight: FontWeight.bold),
),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: FutureBuilder<List<DatabaseModel>>(
future: databaseProvider.getAllData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
var common = snapshot.data[index];
return Card(
elevation: 5.0,
child: ListTile(
leading: SizedBox(
height: 85,
width: 79,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
image: DecorationImage(
image:
NetworkImage(common['imageUrl']),
fit: BoxFit.cover)),
),
),
title: Text(common['title']),
isThreeLine: true,
subtitle: Text(common['footerTitle']),
trailing: Column(
children: <Widget>[
Text(common['createDate']),
Text(common['category'])
],
),
),
);
});
} else {}
return Center(
child: CircularProgressIndicator(),
);
},
)
)),
);
}
}
I all of data in Home Page and in this Page when I pressed on button it display Method was called null. This type I handle onclick.
onPressed: () async {
print('added data');
dbHelper.addToDatabase(DatabaseModel(
imageUrl: allNewsDetail[index]['image_url'],
category: allNewsDetail[index]['category'],
footerTitle: allNewsDetail[index]['footer_title'],
createDate: allNewsDetail[index]['created_date'],
newsLink: allNewsDetail[index]['news_link'],
description: allNewsDetail[index]['description'],
title: allNewsDetail[index]['title']));
Navigator.push(context,MaterialPageRoute(builder: (context) =>BookMark()));
}
When click on button it displays this error.
The method 'getAllData' was called on null.
Receiver: null
Tried calling: getAllData()
Please check This code I give me solution for it.

You are not passing in the databaseProvider into this class and that is why you are getting null!

Related

How to retrieve particular data from id on flutter

How to retrieve particular data from id on flutter and want to show data inside list view. I have created view, insert, delete and update operations.i used sqflite
my code is below.
main.dart file
class _SqliteAppState extends State<SqliteApp> {
int? selectedId;
final textController = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: TextField(
controller: textController,
),
),
body: Center(
child: FutureBuilder<List<Grocery>>(
future: DatabaseHelper.instance.getGroceries(),
builder: (BuildContext context,
AsyncSnapshot<List<Grocery>> snapshot) {
if (!snapshot.hasData) {
return Center(child: Text('Loading...'));
}
return snapshot.data!.isEmpty
? Center(child: Text('No Groceries in List.'))
: ListView(
children: snapshot.data!.map((grocery) {
return Center(
child: Card(
color: selectedId == grocery.id
? Colors.white70
: Colors.white,
child: ListTile(
title: Text(grocery.name),
onTap: () {
setState(() {
if (selectedId == null) {
textController.text = grocery.name;
selectedId = grocery.id;
} else {
textController.text = '';
selectedId = null;
}
});
},
onLongPress: () {
setState(() {
DatabaseHelper.instance.remove(grocery.id!);
});
},
),
),
);
}).toList(),
);
}),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.save),
onPressed: () async {
selectedId != null
? await DatabaseHelper.instance.update(
Grocery(id: selectedId, name: textController.text),
)
: await DatabaseHelper.instance.add(
Grocery(name: textController.text),
);
setState(() {
textController.clear();
selectedId = null;
});
},
),
),
);
}
The model class code is below
Grocery({this.id, required this.name});
factory Grocery.fromMap(Map<String, dynamic> json) => new Grocery(
id: json['id'],
name: json['name'],
);
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
}; } }
This is my db_helper class code. I have created view, insert, delete and update operations.
class DatabaseHelper {
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database? _database;
Future<Database> get database async => _database ??= await _initDatabase();
Future<Database> _initDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, 'groceries.db');
return await openDatabase(
path,
version: 1,
onCreate: _onCreate,
);
}
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE groceries(
id INTEGER PRIMARY KEY,
name TEXT
)
''');
}
Future<List<Grocery>> getGroceries() async {
Database db = await instance.database;
var groceries = await db.query('groceries', orderBy: 'name');
List<Grocery> groceryList = groceries.isNotEmpty
? groceries.map((c) => Grocery.fromMap(c)).toList()
: [];
return groceryList;
}
Future<int> add(Grocery grocery) async {
Database db = await instance.database;
return await db.insert('groceries', grocery.toMap());
}
Future<int> remove(int id) async {
Database db = await instance.database;
return await db.delete('groceries', where: 'id = ?', whereArgs: [id]);
}
Future<int> update(Grocery grocery) async {
Database db = await instance.database;
return await db.update('groceries', grocery.toMap(),
where: "id = ?", whereArgs: [grocery.id]);
}
}
You can use this function to get the data by id:
Future<List<Grocery>> getGrocerieById(int id) async {
Database db = await instance.database;
var groceries =
await db.query('groceries', where: 'id = ?', whereArgs: [id]);
List<Grocery> groceryList = groceries.isNotEmpty
? groceries.map((c) => Grocery.fromMap(c)).toList()
: [];
return groceryList;
}

Flutter - How to fix `Instance of 'Future<int>'` when querying SQLite database

Since I want to test foreign key features with SQLite, I am trying to make a simple app.
The app should display inventory information like this:
I made two tables on the SQLite database and added records directly by querying on Android Studio's Database Inspector.
items table
prices table
I tried to get each item's price by querying in the app, but Instance of 'Future<int>' displayed. How can I display item prices correctly?
Main code
class SqliteForeignKeyScreen extends StatefulWidget {
const SqliteForeignKeyScreen({
Key? key,
}) : super(key: key);
#override
State<SqliteForeignKeyScreen> createState() => _SqliteForeignKeyScreenState();
}
class _SqliteForeignKeyScreenState extends State<SqliteForeignKeyScreen> {
Future<List<Item>>? _itemsList;
void _updateItemsList() {
setState(() {
_itemsList = DatabaseHelper.instance.getAllItemsList();
});
}
#override
void initState() {
super.initState();
_updateItemsList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Items'),
),
body: FutureBuilder(
future: _itemsList,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
Text('ERROR: ${snapshot.error}');
}
if (snapshot.hasData == false) {
return const CircularProgressIndicator();
}
if (snapshot.data.length == null || snapshot.data.length == 0) {
return const Text('no items');
}
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index) {
return _buildItemCards(snapshot.data[index]);
});
},
),
);
}
_buildItemCards(Item item) {
var price = DatabaseHelper.instance.getItemPrice(item.id!);
print('item: ${item.name}, price: ${price}G');
return Card(
child: ListTile(
title: Text(item.name),
subtitle: Text('${price}G'),
),
);
}
}
database_helper.dart
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._instance();
static Database? _db;
DatabaseHelper._instance();
Future<Database?> get db async {
_db ??= await _initDb();
return _db;
}
void _configureDb(Database db) async {
await db.execute('PRAGMA foreign_keys = ON;');
}
void _createDb(Database db, int version) async {
await db.execute('CREATE TABLE items('
'id INTEGER PRIMARY KEY AUTOINCREMENT,'
'name TEXT'
');');
await db.execute('CREATE TABLE prices('
'id INTEGER PRIMARY KEY AUTOINCREMENT,'
'item_id INTEGER,'
'price INTEGER,'
'FOREIGN KEY(item_id) REFERENCES items(id)'
');');
}
Future<Database> _initDb() async {
var databasePath = await getDatabasesPath();
String path = p.join(databasePath, 'inventory.db');
final inventoryDb = await openDatabase(path,
version: 1, onConfigure: _configureDb, onCreate: _createDb);
return inventoryDb;
}
Future<List<Map>> getAllItemsMapList() async {
Database? db = await this.db;
final List<Map<String, dynamic>> result = await db!.query('items');
return result;
}
Future<List<Item>> getAllItemsList() async {
final List<Map> itemsMapList = await getAllItemsMapList();
final List<Item> itemsList = [];
for (var itemMap in itemsMapList) {
itemsList.add(Item.fromMap(itemMap));
}
return itemsList;
}
Future<int> getItemPrice(int itemId) async {
final Database? db = await this.db;
final result =
await db!.query('prices', where: 'item_id = ?', whereArgs: [itemId]);
return result[0]['price'] as int;
}
}
item_model.dart
class Item {
int? id;
String name;
Item({
required this.name,
});
Item.withId({
this.id,
required this.name,
});
factory Item.fromMap(Map map) {
return Item.withId(
id: map['id'],
name: map['name'],
);
}
}
Result of print('item: ${item.name}, price: ${price}G');
item: Apple, price: Instance of 'Future<int>'G
item: Banana, price: Instance of 'Future<int>'G
item: Chocolate, price: Instance of 'Future<int>'G
When I changed _buildItemCards like this (added await and async):
_buildItemCards(Item item) async {
var price = await DatabaseHelper.instance.getItemPrice(item.id!);
print('item: ${item.name}, price: ${price}G');
return Card(
child: ListTile(
title: Text(item.name),
subtitle: Text('${price}G'),
),
);
}
The print('item: ${item.name}, price: ${price}G'); shows correctly:
item: Apple, price: 2G
item: Banana, price: 1G
item: Chocolate, price: 3G
However, the error type 'Future<dynamic>' is not a subtype of type 'Widget' occurred on the screen.
The getItemPrice is a Future function, so you should await for its result, like this:
var price = await DatabaseHelper.instance.getItemPrice(item.id!);
And also the best way to use async function in build method is using FutureBuilder, so change your _buildItemCards to this:
FutureBuilder<int>(
future: DatabaseHelper.instance.getItemPrice(item.id!),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading....');
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
int price = snapshot.data!;
return Card(
child: ListTile(
title: Text(item.name),
subtitle: Text('${price}G'),
),
);
}
}
},
)

Fetching data from API and storing it to local database error

I'm trying to store data that fetched from API using sqflite
Now I'm getting an error saying...
A value of type 'List' can't be returned from the method 'getAllEmployees' because it has a return type of 'Future<List>'.
Here's my employee_provider.dart file
class EmployeeApiProvider {
Future<List<Employee>> getAllEmployees() async {
var url = "http://demo8161595.mockable.io/employee";
var response = await Dio().get(url);
return employeeFromJson(response.data).map((employee) {
DBProvider.db.createEmployee(employee);
}).toList();
}
}
How to fix this?
And other files relevant to this are...
db_provider.dart
class DBProvider {
static Database? _database;
static final DBProvider db = DBProvider._();
DBProvider._();
Future<Database?> get database async {
if (_database != null) return _database;
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, 'employee_manager.db');
return await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE Employee('
'id INTEGER PRIMARY KEY,'
'email TEXT,'
'firstName TEXT,'
'lastName TEXT,'
'avatar TEXT'
')');
});
}
createEmployee(Employee newEmployee) async {
await deleteAllEmployees();
final db = await database;
final res = await db!.insert('Employee', newEmployee.toJson());
return res;
}
Future<int> deleteAllEmployees() async {
final db = await database;
final res = await db!.rawDelete('DELETE FROM Employee');
return res;
}
Future<List<Employee>> getAllEmployees() async {
final db = await database;
final res = await db!.rawQuery("SELECT * FROM EMPLOYEE");
List<Employee> list =
res.isNotEmpty ? res.map((c) => Employee.fromJson(c)).toList() : [];
return list;
}
}
employee_model.dart
List<Employee> employeeFromJson(String str) =>
List<Employee>.from(json.decode(str).map((x) => Employee.fromJson(x)));
String employeeToJson(List<Employee> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Employee {
int id;
String email;
String firstName;
String lastName;
String avatar;
Employee({
required this.id,
required this.email,
required this.firstName,
required this.lastName,
required this.avatar,
});
factory Employee.fromJson(Map<String, dynamic> json) => Employee(
id: json["id"],
email: json["email"],
firstName: json["firstName"],
lastName: json["lastName"],
avatar: json["avatar"],
);
Map<String, dynamic> toJson() => {
"id": id,
"email": email,
"firstName": firstName,
"lastName": lastName,
"avatar": avatar,
};
}
home.dart
class _HomeState extends State<AbcView> {
var isLoading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Api to sqlite'),
centerTitle: true,
actions: <Widget>[
Container(
padding: const EdgeInsets.only(right: 10.0),
child: IconButton(
icon: const Icon(Icons.settings_input_antenna),
onPressed: () async {
await _loadFromApi();
},
),
),
Container(
padding: const EdgeInsets.only(right: 10.0),
child: IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
await _deleteData();
},
),
),
],
),
body: isLoading
? const Center(
child: CircularProgressIndicator(),
)
: _buildEmployeeListView(),
);
}
_loadFromApi() async {
setState(() {
isLoading = true;
});
var apiProvider = EmployeeApiProvider();
await apiProvider.getAllEmployees();
await Future.delayed(const Duration(seconds: 2));
setState(() {
isLoading = false;
});
}
_deleteData() async {
setState(() {
isLoading = true;
});
await DBProvider.db.deleteAllEmployees();
await Future.delayed(const Duration(seconds: 1));
setState(() {
isLoading = false;
});
}
_buildEmployeeListView() {
return FutureBuilder(
future: DBProvider.db.getAllEmployees(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.separated(
separatorBuilder: (context, index) => const Divider(
color: Colors.black12,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Text(
"${index + 1}",
style: const TextStyle(fontSize: 20.0),
),
title: Text(
"Name: ${snapshot.data[index].firstName} ${snapshot.data[index].lastName} "),
subtitle: Text('EMAIL: ${snapshot.data[index].email}'),
);
},
);
}
},
);
}
}
Maybe you could try to add await in front of the DBProvider.db.createEmployee?
class EmployeeApiProvider {
Future<List<Employee>> getAllEmployees() async {
var url = "http://demo8161595.mockable.io/employee";
var response = await Dio().get(url);
return employeeFromJson(response.data).map((employee) async {
await DBProvider.db.createEmployee(employee);
}).toList();
}
}

Flutter: Not able to access main_img,title from model?

eg:details about the questions....................................................................I have a model class Name is RasiphalaContent . i want to access main_img,title to display in home page. but not able to access in home page.below i've attached the model class and Home page code please find and check it.
Home Page:
import 'dart:io';
import 'dart:math';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'DetailsPage.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'Model/RasiphalaContent.dart';
var paddingBottom = 48.0;
var androidDeviceInfo;
var identifier;
var token;
var token1;
class HomePage extends StatelessWidget {
final String apiUrl = "https://www.sofikart.com/MobileApi/banners";
final String apiUrl1 =
"https://wayindia.net/indigo/odia_rashifal/rasifhala.php";
Future<RasiphalaContent> fetchData() async {
final response = await http.get(Uri.parse(apiUrl1));
print(response.body);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return RasiphalaContent.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ଆଜିର ରାଶିଫଳ'),
centerTitle: true,
),
body: Container(
child: FutureBuilder<RasiphalaContent>(
future: fetchData(),
builder: (BuildContext context, snapshot) {
final data = snapshot.data;
_getId();
if (snapshot.hasData) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 20,
mainAxisSpacing: 25,
),
padding: EdgeInsets.all(13),
shrinkWrap: true,
itemBuilder: (ctx, index) {
return InkWell(
child: Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Column(
children: [
Expanded(
flex: 9,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(12)),
child: Image.network(,
fit: BoxFit.fill)),
),
Expanded(
flex: 2,
child: Text(
title(),
style: TextStyle(
color: Colors.black, fontSize: 17),
)),
],
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsPage(),
),
);
},
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
),
);
}
Future<String?> _getId() async {
identifier;
final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin();
if (Platform.isAndroid) {
// import 'dart:io'
var build = await deviceInfoPlugin.androidInfo;
identifier = build.androidId!; //UUID for Android
token = await FirebaseMessaging.instance.getToken();
token1 = await FirebaseMessaging.instance.getToken();
login();
}
}
login() async {
final response = await http.post(
"https://wayindia.net/indigo/odia_rashifal/device_create.php",
body: {
//"flag": 1.toString(),
"device_id": identifier,
"device_token": token,
});
final data = jsonDecode(response.body);
int value = data['status'];
String message = data['message'];
if (value == 1) {
print(message);
} else {
print("fail");
print(message);
}
}
}
Model Class :
// To parse this JSON data, do
//
// final rasiphalaContent = rasiphalaContentFromJson(jsonString);
import 'dart:convert';
RasiphalaContent rasiphalaContentFromJson(String str) => RasiphalaContent.fromJson(json.decode(str));
String rasiphalaContentToJson(RasiphalaContent data) => json.encode(data.toJson());
class RasiphalaContent {
RasiphalaContent({
required this.status,
required this.message,
required this.data,
});
int status;
String message;
List<Datum> data;
factory RasiphalaContent.fromJson(Map<String, dynamic> json) => RasiphalaContent(
status: json["status"],
message: json["message"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
required this.id,
required this.title,
required this.content,
required this.engTitle,
required this.mainImg,
required this.image2,
required this.image3,
required this.image4,
});
String id;
String title;
String content;
String engTitle;
String mainImg;
String image2;
String image3;
String image4;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
title: json["title"],
content: json["content"],
engTitle: json["eng_title"],
mainImg: json["main_img"],
image2: json["image_2"],
image3: json["image_3"],
image4: json["image_4"],
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"content": content,
"eng_title": engTitle,
"main_img": mainImg,
"image_2": image2,
"image_3": image3,
"image_4": image4,
};
}

How to implement search delegate with sqflite flutter

I have created an app that stores some notes in sqlite database. I did all CRUD operations and it's working well, but when I'm trying to make search operation inside my database with SearchDelegate, I got some problem. I'll show you my code before I make search with SearchDelegate
databaseHelper:
import 'dart:async';
import 'package:plants/model/plant.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static final DatabaseHelper _instance = new DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
final String tableNote = 'noteTable';
final String columnId = 'id';
final String columnLocation = 'location';
final String columnTitle = 'title';
final String columnDescription = 'description';
static Database _db;
DatabaseHelper.internal();
Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDb();
return _db;
}
initDb() async {
String databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'notes.db');
// await deleteDatabase(path); // just for testing
var db = await openDatabase(path, version: 1, onCreate: _onCreate);
return db;
}
void _onCreate(Database db, int newVersion) async {
await db.execute(
'CREATE TABLE $tableNote($columnId INTEGER PRIMARY KEY,$columnLocation TEXT, $columnTitle TEXT, $columnDescription TEXT)');
}
Future<int> saveNote(Note note) async {
var dbClient = await db;
var result = await dbClient.insert(tableNote, note.toMap());
// var result = await dbClient.rawInsert(
// 'INSERT INTO $tableNote ($columnTitle, $columnDescription) VALUES (\'${note.title}\', \'${note.description}\')');
return result;
}
Future<List> getAllNotes() async {
var dbClient = await db;
var result = await dbClient.query(tableNote, columns: [columnId, columnLocation , columnTitle, columnDescription]);
// var result = await dbClient.rawQuery('SELECT * FROM $tableNote');
return result.toList();
}
Future<int> getCount() async {
var dbClient = await db;
return Sqflite.firstIntValue(await dbClient.rawQuery('SELECT COUNT(*) FROM $tableNote'));
}
Future<Note> getNote(int id) async {
var dbClient = await db;
List<Map> result = await dbClient.query(tableNote,
columns: [columnId, columnLocation , columnTitle, columnDescription],
where: '$columnId = ?',
whereArgs: [id]);
// var result = await dbClient.rawQuery('SELECT * FROM $tableNote WHERE $columnId = $id');
if (result.length > 0) {
return new Note.fromMap(result.first);
}
return null;
}
Future<int> deleteNote(int id) async {
var dbClient = await db;
return await dbClient.delete(tableNote, where: '$columnId = ?', whereArgs: [id]);
// return await dbClient.rawDelete('DELETE FROM $tableNote WHERE $columnId = $id');
}
Future<int> updateNote(Note note) async {
var dbClient = await db;
return await dbClient.update(tableNote, note.toMap(), where: "$columnId = ?", whereArgs: [note.id]);
// return await dbClient.rawUpdate(
// 'UPDATE $tableNote SET $columnTitle = \'${note.title}\', $columnDescription = \'${note.description}\' WHERE $columnId = ${note.id}');
}
Future close() async {
var dbClient = await db;
return dbClient.close();
}
}
Class Notes
class Note {
int _id;
String _location;
String _title;
String _description;
Note(this._location,this._title, this._description);
Note.map(dynamic obj) {
this._id = obj['id'];
this._location = obj['location'];
this._title = obj['title'];
this._description = obj['description'];
}
int get id => _id;
String get location => _location;
String get title => _title;
String get description => _description;
Map<String, dynamic> toMap() {
var map = new Map<String, dynamic>();
if (_id != null) {
map['id'] = _id;
}
map['location'] = _location;
map['title'] = _title;
map['description'] = _description;
return map;
}
Note.fromMap(Map<String, dynamic> map) {
this._id = map['id'];
this._location = map ['location'];
this._title = map['title'];
this._description = map['description'];
}
}
List.dart
import 'package:flutter/material.dart';
import 'package:plants/AddPlant.dart';
import 'package:plants/model/plant.dart';
import 'database/dbhelper.dart';
class ListViewNote extends StatefulWidget {
#override
State<StatefulWidget> createState() => new ListViewNoteState();
}
class ListViewNoteState extends State<ListViewNote> {
List<Note> items = new List();
DatabaseHelper db = new DatabaseHelper();
#override
void initState() {
super.initState();
db.getAllNotes().then((notes) {
setState(() {
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Plant List',
),
centerTitle: true,
actions: <Widget>[
IconButton(icon: Icon(Icons.search,
color: Colors.white,), onPressed: (){
showSearch(context: context,
delegate: DataSearch(this.items));
})
],
),
body: Center(
child: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.all(15.0),
itemBuilder: (context, position) {
return Dismissible(
background: stackBehindDismiss(),
key: ObjectKey(items[position]),
child: Card(
elevation: 2.0,
margin: new EdgeInsets.symmetric(horizontal: 0.0,vertical: 2.0),
child: Column(
children: <Widget>[
ListTile(
title: Text(
'${items[position].title}',
style: TextStyle(
fontSize: 22.0,
color: Colors.deepOrangeAccent,
),
),
subtitle: Text(
'${items[position].description}' + '' + '${items[position].location}',
style: new TextStyle(
fontSize: 18.0,
fontStyle: FontStyle.italic,
),
),
onTap: () => _navigateToNote(context, items[position]),
),
],
),
),
onDismissed: (dirction){
var item = items.elementAt(position);
_deleteNote(context, items[position], position);
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Item deleted"),
));
},
);
}
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.green[700],
child: Icon(Icons.add),
onPressed: () => _createNewNote(context),
),
);
}
void _deleteNote(BuildContext context, Note note, int position) async {
db.deleteNote(note.id).then((notes) {
setState(() {
items.removeAt(position);
});
});
}
void _navigateToNote(BuildContext context, Note note) async {
String result = await Navigator.push(
context,MaterialPageRoute(builder: (context) => NoteScreen(note)),
);
if (result == 'update') {
db.getAllNotes().then((notes) {
setState(() {
items.clear();
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
}
void _createNewNote(BuildContext context) async {
String result = await Navigator.push(
context,MaterialPageRoute(builder: (context) => NoteScreen(Note('', '', ''))),
);
if (result == 'save') {
db.getAllNotes().then((notes) {
setState(() {
items.clear();
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
}
stackBehindDismiss() {
return Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20.0),
color: Colors.green[700],
child: Icon(
Icons.delete,
color: Colors.white,
),
);
}
}
class DataSearch extends SearchDelegate<Note> {
DatabaseHelper db = new DatabaseHelper();
final List<Note> items = new List();
List<Note> suggestion = new List();
// ListViewNoteState i = ListViewNoteState();
DataSearch(this.suggestion);
#override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(icon: Icon(Icons.clear), onPressed: () {
query = '';
} )
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: (){
close(context, null);
},
);
}
#override
Widget buildResults(BuildContext context) {
}
#override
Widget buildSuggestions(BuildContext context) {
final suggestion = query.isEmpty
? items
: items.where((target) => target.title.startsWith(query)).toList();
if(items.isEmpty)
{
print("Null");
}
return ListView.builder(
itemBuilder: (context, position)=>
ListTile(
title: Text(items[position].title),
),
itemCount: suggestion.length,
);
}
}
On CRUD, everything is working well and I'm adding 3 records but when I'm using SearchDelegate to implement search, I not getting any result.
The thing I need is to searchlist from database using searchbar
Try this:
return ListView.builder(
itemBuilder: (context, index)=>
ListTile(
title: Text(suggestion[index].title),
),
It should work and display the right results, at least mine is working this way, but I think you'll have to point to items list when you build your results or when you tap to open it or something like that.