简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM