我想删除列表视图中的最后一项

时间:2020-05-18 05:40:11

标签: listview flutter dart

我要删除最后一项并从数据库表中删除。 但是,删除最后一个项目时出现错误。这是消息下方的错误代码。

''' RangeError(索引):无效值:不在0..6范围内,包括7 '''

这是Dart的代码。

import 'package:flutter/material.dart';
import 'package:technewsapp/saved_newsdata.dart';
import 'package:technewsapp/dbhealper.dart';
import 'webview_screen.dart';
import 'package:flutter_slidable/flutter_slidable.dart';

final dbHelper = DatabaseHelper.instance;

class Favorite extends StatefulWidget {
  @override
  _Favorite createState() => _Favorite();
}
class _Favorite extends State<Favorite> {

  SlidableController slidableController;
  List<SavedNews> savedNews = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _queryAll();
  }

  Animation<double> _rotationAnimation;
  Color _fabColor = Colors.blue;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Favorite"),
      ),
      body: Center(
        child: OrientationBuilder(
          builder: (context, orientation) => _listViewWidget(
              context,
              orientation == Orientation.portrait
                  ? Axis.vertical
                  : Axis.horizontal),
        ),
      ),
    );
  }

  void _queryAll() async {
    final allRows = await dbHelper.queryAllRows();
    allRows.forEach((row) => savedNews.add(SavedNews.fromMap(row)));
    print('Query done.');
    setState(() {});
  }

  Widget _listViewWidget(BuildContext context, Axis direction) {
    return ListView.builder(
      scrollDirection: direction,
      itemCount: savedNews.length,
      itemBuilder: (context, index) {
        final Axis slideDirection = direction == Axis.horizontal ? Axis.vertical : Axis.horizontal;
        return _getSlideWithLists(context, index, slideDirection);
      },
    );
  }

  Widget _getSlideWithLists(BuildContext context, int index, Axis direction){
    return Slidable.builder(
      key: Key(savedNews[index].id),
      controller: slidableController,
      direction: direction,

      dismissal: SlidableDismissal(
        child: SlidableDrawerDismissal(),
        onDismissed: (actionType) {
          setState(() {
            print("index is $index");
            print("length is ${savedNews.length}");
            savedNews.removeAt(index);
            if(index + 1 == savedNews.length){
              _delete(savedNews[savedNews.length].id);
            } else {
              _delete(savedNews[index].id);
            }
          });
        },
      ),
      child: CardListItems(savedNews: savedNews, index: index),
      secondaryActionDelegate: SlideActionBuilderDelegate(
          actionCount: 1,
          builder: (context, index, animation, renderingMode) {
            return IconSlideAction(
              caption: 'Delete',
              color: renderingMode == SlidableRenderingMode.slide
                  ? Colors.red.withOpacity(animation.value)
                  : Colors.red,
              icon: Icons.delete,
              onTap: ((){
                _delete(savedNews[index].id);
                savedNews.removeAt(index);
              }),
            );
          }
      ), actionPane: SlidableScrollActionPane(),
    );
  }
  void _delete(id) async {
    // Assuming that the number of rows is the id for the last row.
    final rowsDeleted = await dbHelper.delete(id);
  }
}

class CardListItems extends StatelessWidget {

  final int index;
  final List<SavedNews> savedNews;

  const CardListItems({
    Key key,
    @required this.savedNews,
    @required this.index,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        title: Text(
          '${savedNews[index].title}',
          style: TextStyle(
              fontSize: 18.0,
              color: Colors.black,
              fontWeight: FontWeight.bold),
        ),
        leading: Padding(
          padding: const EdgeInsets.all(8.0),
          child: SizedBox(
            child: savedNews[index].urlToImage == null
                ? Image(
              image: AssetImage('assets/image/noImage.png'),
            )
                : Image.network('${savedNews[index].urlToImage}'),
            height: 100.0,
            width: 100.0,
          ),
        ),
        onTap: () {
          print(savedNews[index].url);
          Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) =>
                    WebViewScreen(url: savedNews[index].url)),
          );
        },
      ),

    );
  }
}

这里是数据库控制器。

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:technewsapp/saved_newsdata.dart';

class DatabaseHelper {

  static final _databaseName = "savednews.db";
  static final _databaseVersion = 1;

  static final table = 'savednews_table';

  static final columnId = 'id';
  static final columnTitle = 'title';
  static final columnUrl = 'url';
  static final columnUrlToImage = 'urlToImage';

  // make this a singleton class
  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

  // only have a single app-wide reference to the database
  static Database _database;
  Future<Database> get database async {
    if (_database != null) return _database;
    // lazily instantiate the db the first time it is accessed
    _database = await _initDatabase();
    return _database;
  }

  // this opens the database (and creates it if it doesn't exist)
  _initDatabase() async {
    String path = join(await getDatabasesPath(), _databaseName);
    return await openDatabase(path,
        version: _databaseVersion,
        onCreate: _onCreate);
  }

  // SQL code to create the database table
  Future _onCreate(Database db, int version) async {
    await db.execute('''
          CREATE TABLE $table (
            $columnId TEXT NOT NULL PRIMARY KEY,
            $columnTitle TEXT NOT NULL,
            $columnUrl TEXT NOT NULL,
            $columnUrlToImage TEXT NOT NULL
          )
          ''');
  }

  // Helper methods

  // Inserts a row in the database where each key in the Map is a column name
  // and the value is the column value. The return value is the id of the
  // inserted row.
  Future<int> insert(SavedNews savedNews) async {
    Database db = await instance.database;
    return await db.insert(table, {'id': savedNews.id, 'title': savedNews.title, 'url': savedNews.url, 'urlToImage': savedNews.urlToImage});
  }

  // All of the rows are returned as a list of maps, where each map is
  // a key-value list of columns.
  Future<List<Map<String, dynamic>>> queryAllRows() async {
    Database db = await instance.database;
    return await db.query(table);
  }

  Future<int> delete(String id) async {
    Database db = await instance.database;
    return await db.delete(table, where: '$columnId = ?', whereArgs: [id]);
  }


}

环境

Flutter 1.17.0•频道Beta•https://github.com/flutter/flutter.git 框架•版本e6b34c2b5c(2周前)•2020-05-02 11:39:18 -0700 引擎•版本540786dd51 工具•Dart 2.8.1

V / r

1 个答案:

答案 0 :(得分:1)

savedNews.length - 1 

这将为您工作。