admin管理员组

文章数量:1025779

I am trying to create a web blog with Hacker News API, but every time I try to run, I get this confusing error thrown at me and I do not get it. asked chatgpt, it gave me a solution but I still run into the same error. I am pasting all necessary classes.

first this is my database class.

import 'dart:io';

import 'package:new_flutter/src/models/item_model.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

final newsDbProv2 = NewsDbProv2();

class NewsDbProv2 {
  static const _dbName = "items.db";
  static const _dbVersion = 1;
  static const _tableName = "Items";

  Database? db;

  /// INITIALIZING THE DATABASE......
  Future<void> init() async {
    // if (db != null) return;
    if (db == null) {
      try {
        Directory documentsDirectory = await getApplicationDocumentsDirectory();
        final path = join(documentsDirectory.path, _dbName);
        db = await openDatabase(path,
            version: _dbVersion, onCreate: createTable);
      } catch (e) {
        print('Error initializing database: $e');
      }
    }
  }

  ///CREATING THE DATABASE TABLE........
  Future<void> createTable(Database newDb, int version) async {
    try {
      await newDb.execute("""
          CREATE TABLE $_tableName
          (
            id INTEGER PRIMARY KEY,
            type TEXT,
            by TEXT,
            time INTEGER,
            text TEXT,
            parent INTEGER,
            kids BLOB,
            dead INTEGER,
            deleted INTEGER,
            url TEXT,
            score INTEGER,
            title TEXT,
            descendants INTEGER
          )
          """);
    } catch (e) {
      print('Error creating table: $e');
    }
  }

  ///Fetching an ITEM by ID from the DATABASE.....
  Future<ItemModel?> fetchItem(int id) async {
    try {
      if (db == null) await init();

      final maps = await db!.query(
        _tableName,
        columns: null,
        where: "id = ?",
        whereArgs: [id],
      );

      if (maps.isNotEmpty) {
        return ItemModel.fromDB(maps.first);
      }
    } catch (e) {
      print('Error fetching item from the database: $e');
    }
    return null;
  }

  Future<int> addItem(ItemModel item) async {
    try {
      if (db == null) await init();

      return await db!.transaction((txn) async {
        return await txn.insert(
          // return db!.insert(
          _tableName,
          item.toMapForDb(),
          conflictAlgorithm: ConflictAlgorithm.ignore,
        );
      });
    } catch (e) {
      print('Error adding item to database: $e');
      return 0;
    }
  }

  // Future<int> addItem(ItemModel item) async {
  //   return await db!.transaction((txn) async {
  //     return await txn.insert(
  //       // return db!.insert(
  //       _tableName,
  //       item.toMapForDb(),
  //       conflictAlgorithm: ConflictAlgorithm.ignore,
  //     );
  //   });
  // }
}
// Future<List<int>> fetchTopIds() {
//   // TODO: implement fetchTopIds
//   throw UnimplementedError();
// }

this is the api class

import 'dart:convert';

import 'package:http/http.dart' show Client;
import 'package:new_flutter/src/models/item_model.dart';

const rootDomain = '';

class NewsApiProv2 {
  Client client = Client();

  /// Fetching Top story IDs from the API.......
  Future<List<int>> fetchTopIds() async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/topstories.json'))
          .timeout(const Duration(seconds: 10));

      if (response.statusCode == 200) {
        final ids = json.decode(response.body);

        return ids.cast<int>();
      } else {
        print("Error: Failed to fetch top IDs. Status: ${response.statusCode}");
      }
    } catch (e) {
      print('Exception during fetchTopIds: $e');
    }
    return [];
  }

  /// Fetching a specific Story/ITEM by ID........
  Future<ItemModel?> fetchItem(int id) async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/item/$id.json'))
          .timeout(const Duration(seconds: 10));
      if (response.statusCode == 200) {
        final parsedJson = json.decode(response.body);

        if (parsedJson == null || parsedJson.isEmpty) {
          print('Empty or null response for item with id $id');
          return null;
        }
        return ItemModel.fromJson(parsedJson);
      } else {
        print(
            'Failed to fetch item with id $id, Status Code: ${response.statusCode}');
        throw Exception('Failed to load item');
      }
    } catch (e) {
      print('Exception during fetchItem: $e');
    }
    return null;
  }
}

This is repository class:

import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_api_prov2.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_db_prov_2.dart';

class RepositoryProv2 {
  /// Initialize instances of the providers
  final NewsApiProv2 _newsApiProvider = NewsApiProv2();
  final NewsDbProv2 _newsDbProvider = NewsDbProv2();

  /// Fetch the top story IDs from the API
  Future<List<int>> fetchTopIds() async {
    try {
      return await _newsApiProvider.fetchTopIds();
    } catch (e) {
      print("Error fetching top IDs: $e");
      return [];
    }
  }

  /// Fetch an individual item from either API or Database (cache)
  Future<ItemModel?> fetchItems(int id) async {
    try {
      /// First try fetching the item from the database (cache)
      ItemModel? item = await _newsDbProvider.fetchItem(id);

      /// If the item is not found in the database, fetch from the API
      if (item == null) {
        item = await _newsApiProvider.fetchItem(id);

        /// If the item was found, save it in the database (cache)
        if (item != null) {
          await _newsDbProvider.addItem(item);
        }
      }
      return item;
    } catch (e) {
      print("Error fetching item: $e");
      return null;
    }
  }
}

This is my bloc class:

import 'package:flutter/cupertino.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/repository_prov2.dart';

class NewsBloc extends ChangeNotifier {
  final RepositoryProv2 _prov2 = RepositoryProv2();

  List<int> _topIds = [];
  final List<ItemModel> _items = [];
  bool _isLoading = false;

  List<int> get topIds => _topIds;

  List<ItemModel> get items => _items;

  bool get isLoading => _isLoading;

  ///Fetch Top IDs from the API
  Future<void> fetchTopIds() async {
    _isLoading = true;
    notifyListeners(); //Notify UI to update

    try {
      _topIds = await _prov2.fetchTopIds();
    } catch (e) {
      print('Error fetching top IDs: $e');
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  /// Fetching ITEMS by IDs
  Future<ItemModel?> fetchItem(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      final item = await _prov2.fetchItems(id);
      if (item != null) {
        _items.add(item);
      }
    } catch (e) {
      print('Error fetching item: $e');
    } finally {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _isLoading = false;
        notifyListeners();
      });
    }
    return null;
  }
}

this is the app.dart:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/screens/news_list.dart';
import 'package:provider/provider.dart';

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => NewsBloc(),
      child: MaterialApp(
        title: 'News!',
        home: NewsList(),
      ),
    );
  }
}

this is App.dart

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/widgets/news_list_tile.dart';
import 'package:provider/provider.dart';

class NewsList extends StatelessWidget {
  const NewsList({super.key});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    ///Fetch Top IDs when the screen loads
    if (bloc.topIds.isEmpty) {
      bloc.fetchTopIds();
    }

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.blue,
        elevation: 5,
        title: const Text(
          'Top News',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: buildList(bloc),
    );
  }

  Widget buildList(NewsBloc bloc) {
    return Consumer<NewsBloc>(
      builder: (context, bloc, child) {
        if (bloc.isLoading) {
          return Center(
            child: CircularProgressIndicator(color: Colors.blue),
          );
        }

        return ListView.builder(
          itemCount: bloc.topIds.length,
          itemBuilder: (context, int index) {
            return NewsListTile(
              itemId: bloc.topIds[index],
            );
          },
        );
      },
    );
  }
}

This is news list tile class:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:provider/provider.dart';

import '../blocs/latest_bloc_provider/news_bloc.dart';

class NewsListTile extends StatelessWidget {
  final int? itemId;

  const NewsListTile({super.key, this.itemId});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    return FutureBuilder<ItemModel?>(
      future: bloc.fetchItem(itemId!),
      builder: (context, snapshot) {
        // if (!snapshot.hasData) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Text('Still loading item $itemId');
        }

        if (snapshot.hasError) {
          return Text('Error loading item $itemId: ${snapshot.error}');
        }
        if (!snapshot.hasData) {
          return Text('No data available');
        }
        return Text(snapshot.data!.title);
      },
    );
  }
}

The errors I am receiving from this is confusing and this is it:

======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for NewsBloc:
setState() or markNeedsBuild() called during build.

This _InheritedProviderScope<NewsBloc?> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<NewsBloc?>
  value: Instance of 'NewsBloc'
  listening to value
The widget which was currently being built when the offending call was made was: NewsListTile
  dirty
  dependencies: [_InheritedProviderScope<NewsBloc?>]
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5177:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5189:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:577:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:437:24)
#4      NewsBloc.fetchItem (package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart:36:5)
#5      NewsListTile.build (package:new_flutter/src/widgets/news_list_tile.dart:17:20)
#6      StatelessElement.build (package:flutter/src/widgets/framework.dart:5687:49)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5617:15)
The NewsBloc sending notification was: Instance of 'NewsBloc'
====================================================================================================
D/EGL_emulation(13392): app_time_stats: avg=1797.18ms min=1797.18ms max=1797.18ms count=1
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction

I am trying to create a web blog with Hacker News API, but every time I try to run, I get this confusing error thrown at me and I do not get it. asked chatgpt, it gave me a solution but I still run into the same error. I am pasting all necessary classes.

first this is my database class.

import 'dart:io';

import 'package:new_flutter/src/models/item_model.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

final newsDbProv2 = NewsDbProv2();

class NewsDbProv2 {
  static const _dbName = "items.db";
  static const _dbVersion = 1;
  static const _tableName = "Items";

  Database? db;

  /// INITIALIZING THE DATABASE......
  Future<void> init() async {
    // if (db != null) return;
    if (db == null) {
      try {
        Directory documentsDirectory = await getApplicationDocumentsDirectory();
        final path = join(documentsDirectory.path, _dbName);
        db = await openDatabase(path,
            version: _dbVersion, onCreate: createTable);
      } catch (e) {
        print('Error initializing database: $e');
      }
    }
  }

  ///CREATING THE DATABASE TABLE........
  Future<void> createTable(Database newDb, int version) async {
    try {
      await newDb.execute("""
          CREATE TABLE $_tableName
          (
            id INTEGER PRIMARY KEY,
            type TEXT,
            by TEXT,
            time INTEGER,
            text TEXT,
            parent INTEGER,
            kids BLOB,
            dead INTEGER,
            deleted INTEGER,
            url TEXT,
            score INTEGER,
            title TEXT,
            descendants INTEGER
          )
          """);
    } catch (e) {
      print('Error creating table: $e');
    }
  }

  ///Fetching an ITEM by ID from the DATABASE.....
  Future<ItemModel?> fetchItem(int id) async {
    try {
      if (db == null) await init();

      final maps = await db!.query(
        _tableName,
        columns: null,
        where: "id = ?",
        whereArgs: [id],
      );

      if (maps.isNotEmpty) {
        return ItemModel.fromDB(maps.first);
      }
    } catch (e) {
      print('Error fetching item from the database: $e');
    }
    return null;
  }

  Future<int> addItem(ItemModel item) async {
    try {
      if (db == null) await init();

      return await db!.transaction((txn) async {
        return await txn.insert(
          // return db!.insert(
          _tableName,
          item.toMapForDb(),
          conflictAlgorithm: ConflictAlgorithm.ignore,
        );
      });
    } catch (e) {
      print('Error adding item to database: $e');
      return 0;
    }
  }

  // Future<int> addItem(ItemModel item) async {
  //   return await db!.transaction((txn) async {
  //     return await txn.insert(
  //       // return db!.insert(
  //       _tableName,
  //       item.toMapForDb(),
  //       conflictAlgorithm: ConflictAlgorithm.ignore,
  //     );
  //   });
  // }
}
// Future<List<int>> fetchTopIds() {
//   // TODO: implement fetchTopIds
//   throw UnimplementedError();
// }

this is the api class

import 'dart:convert';

import 'package:http/http.dart' show Client;
import 'package:new_flutter/src/models/item_model.dart';

const rootDomain = 'https://hacker-news.firebaseio/v0';

class NewsApiProv2 {
  Client client = Client();

  /// Fetching Top story IDs from the API.......
  Future<List<int>> fetchTopIds() async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/topstories.json'))
          .timeout(const Duration(seconds: 10));

      if (response.statusCode == 200) {
        final ids = json.decode(response.body);

        return ids.cast<int>();
      } else {
        print("Error: Failed to fetch top IDs. Status: ${response.statusCode}");
      }
    } catch (e) {
      print('Exception during fetchTopIds: $e');
    }
    return [];
  }

  /// Fetching a specific Story/ITEM by ID........
  Future<ItemModel?> fetchItem(int id) async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/item/$id.json'))
          .timeout(const Duration(seconds: 10));
      if (response.statusCode == 200) {
        final parsedJson = json.decode(response.body);

        if (parsedJson == null || parsedJson.isEmpty) {
          print('Empty or null response for item with id $id');
          return null;
        }
        return ItemModel.fromJson(parsedJson);
      } else {
        print(
            'Failed to fetch item with id $id, Status Code: ${response.statusCode}');
        throw Exception('Failed to load item');
      }
    } catch (e) {
      print('Exception during fetchItem: $e');
    }
    return null;
  }
}

This is repository class:

import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_api_prov2.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_db_prov_2.dart';

class RepositoryProv2 {
  /// Initialize instances of the providers
  final NewsApiProv2 _newsApiProvider = NewsApiProv2();
  final NewsDbProv2 _newsDbProvider = NewsDbProv2();

  /// Fetch the top story IDs from the API
  Future<List<int>> fetchTopIds() async {
    try {
      return await _newsApiProvider.fetchTopIds();
    } catch (e) {
      print("Error fetching top IDs: $e");
      return [];
    }
  }

  /// Fetch an individual item from either API or Database (cache)
  Future<ItemModel?> fetchItems(int id) async {
    try {
      /// First try fetching the item from the database (cache)
      ItemModel? item = await _newsDbProvider.fetchItem(id);

      /// If the item is not found in the database, fetch from the API
      if (item == null) {
        item = await _newsApiProvider.fetchItem(id);

        /// If the item was found, save it in the database (cache)
        if (item != null) {
          await _newsDbProvider.addItem(item);
        }
      }
      return item;
    } catch (e) {
      print("Error fetching item: $e");
      return null;
    }
  }
}

This is my bloc class:

import 'package:flutter/cupertino.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/repository_prov2.dart';

class NewsBloc extends ChangeNotifier {
  final RepositoryProv2 _prov2 = RepositoryProv2();

  List<int> _topIds = [];
  final List<ItemModel> _items = [];
  bool _isLoading = false;

  List<int> get topIds => _topIds;

  List<ItemModel> get items => _items;

  bool get isLoading => _isLoading;

  ///Fetch Top IDs from the API
  Future<void> fetchTopIds() async {
    _isLoading = true;
    notifyListeners(); //Notify UI to update

    try {
      _topIds = await _prov2.fetchTopIds();
    } catch (e) {
      print('Error fetching top IDs: $e');
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  /// Fetching ITEMS by IDs
  Future<ItemModel?> fetchItem(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      final item = await _prov2.fetchItems(id);
      if (item != null) {
        _items.add(item);
      }
    } catch (e) {
      print('Error fetching item: $e');
    } finally {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _isLoading = false;
        notifyListeners();
      });
    }
    return null;
  }
}

this is the app.dart:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/screens/news_list.dart';
import 'package:provider/provider.dart';

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => NewsBloc(),
      child: MaterialApp(
        title: 'News!',
        home: NewsList(),
      ),
    );
  }
}

this is App.dart

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/widgets/news_list_tile.dart';
import 'package:provider/provider.dart';

class NewsList extends StatelessWidget {
  const NewsList({super.key});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    ///Fetch Top IDs when the screen loads
    if (bloc.topIds.isEmpty) {
      bloc.fetchTopIds();
    }

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.blue,
        elevation: 5,
        title: const Text(
          'Top News',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: buildList(bloc),
    );
  }

  Widget buildList(NewsBloc bloc) {
    return Consumer<NewsBloc>(
      builder: (context, bloc, child) {
        if (bloc.isLoading) {
          return Center(
            child: CircularProgressIndicator(color: Colors.blue),
          );
        }

        return ListView.builder(
          itemCount: bloc.topIds.length,
          itemBuilder: (context, int index) {
            return NewsListTile(
              itemId: bloc.topIds[index],
            );
          },
        );
      },
    );
  }
}

This is news list tile class:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:provider/provider.dart';

import '../blocs/latest_bloc_provider/news_bloc.dart';

class NewsListTile extends StatelessWidget {
  final int? itemId;

  const NewsListTile({super.key, this.itemId});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    return FutureBuilder<ItemModel?>(
      future: bloc.fetchItem(itemId!),
      builder: (context, snapshot) {
        // if (!snapshot.hasData) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Text('Still loading item $itemId');
        }

        if (snapshot.hasError) {
          return Text('Error loading item $itemId: ${snapshot.error}');
        }
        if (!snapshot.hasData) {
          return Text('No data available');
        }
        return Text(snapshot.data!.title);
      },
    );
  }
}

The errors I am receiving from this is confusing and this is it:

======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for NewsBloc:
setState() or markNeedsBuild() called during build.

This _InheritedProviderScope<NewsBloc?> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<NewsBloc?>
  value: Instance of 'NewsBloc'
  listening to value
The widget which was currently being built when the offending call was made was: NewsListTile
  dirty
  dependencies: [_InheritedProviderScope<NewsBloc?>]
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5177:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5189:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:577:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:437:24)
#4      NewsBloc.fetchItem (package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart:36:5)
#5      NewsListTile.build (package:new_flutter/src/widgets/news_list_tile.dart:17:20)
#6      StatelessElement.build (package:flutter/src/widgets/framework.dart:5687:49)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5617:15)
The NewsBloc sending notification was: Instance of 'NewsBloc'
====================================================================================================
D/EGL_emulation(13392): app_time_stats: avg=1797.18ms min=1797.18ms max=1797.18ms count=1
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
Share Improve this question asked Nov 17, 2024 at 3:31 Fred_WolfeFred_Wolfe 8722 gold badges11 silver badges22 bronze badges 3
  • most likely it happens since you are calling notifyListeners inside fetchItems method: it forces another rebuild while building your NewsListTile – pskink Commented Nov 17, 2024 at 7:46
  • you are saying the same thing ChatGPT said brother. still no fix. What is the way around – Fred_Wolfe Commented Nov 17, 2024 at 8:00
  • I am getting a new error now... or more like a warning: I/flutter (14787): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction – Fred_Wolfe Commented Nov 17, 2024 at 10:11
Add a comment  | 

1 Answer 1

Reset to default 1

According to

#4 NewsBloc.fetchItem (package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart:36:5)

the error occurred in bloc class NewsBloc line 36, wrap notifyListeners() in WidgetsBinding.instance.addPostFrameCallback might solve this problem.

  /// Fetching ITEMS by IDs
  Future<ItemModel?> fetchItem(int id) async {
    _isLoading = true;
    WidgetsBinding.instance.addPostFrameCallback((_) {
      notifyListeners();
    });

    try {
      final item = await _prov2.fetchItems(id);
      if (item != null) {
        _items.add(item);
      }
    } catch (e) {
      print('Error fetching item: $e');
    } finally {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _isLoading = false;
        notifyListeners();
      });
    }
    return null;
  }

I am trying to create a web blog with Hacker News API, but every time I try to run, I get this confusing error thrown at me and I do not get it. asked chatgpt, it gave me a solution but I still run into the same error. I am pasting all necessary classes.

first this is my database class.

import 'dart:io';

import 'package:new_flutter/src/models/item_model.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

final newsDbProv2 = NewsDbProv2();

class NewsDbProv2 {
  static const _dbName = "items.db";
  static const _dbVersion = 1;
  static const _tableName = "Items";

  Database? db;

  /// INITIALIZING THE DATABASE......
  Future<void> init() async {
    // if (db != null) return;
    if (db == null) {
      try {
        Directory documentsDirectory = await getApplicationDocumentsDirectory();
        final path = join(documentsDirectory.path, _dbName);
        db = await openDatabase(path,
            version: _dbVersion, onCreate: createTable);
      } catch (e) {
        print('Error initializing database: $e');
      }
    }
  }

  ///CREATING THE DATABASE TABLE........
  Future<void> createTable(Database newDb, int version) async {
    try {
      await newDb.execute("""
          CREATE TABLE $_tableName
          (
            id INTEGER PRIMARY KEY,
            type TEXT,
            by TEXT,
            time INTEGER,
            text TEXT,
            parent INTEGER,
            kids BLOB,
            dead INTEGER,
            deleted INTEGER,
            url TEXT,
            score INTEGER,
            title TEXT,
            descendants INTEGER
          )
          """);
    } catch (e) {
      print('Error creating table: $e');
    }
  }

  ///Fetching an ITEM by ID from the DATABASE.....
  Future<ItemModel?> fetchItem(int id) async {
    try {
      if (db == null) await init();

      final maps = await db!.query(
        _tableName,
        columns: null,
        where: "id = ?",
        whereArgs: [id],
      );

      if (maps.isNotEmpty) {
        return ItemModel.fromDB(maps.first);
      }
    } catch (e) {
      print('Error fetching item from the database: $e');
    }
    return null;
  }

  Future<int> addItem(ItemModel item) async {
    try {
      if (db == null) await init();

      return await db!.transaction((txn) async {
        return await txn.insert(
          // return db!.insert(
          _tableName,
          item.toMapForDb(),
          conflictAlgorithm: ConflictAlgorithm.ignore,
        );
      });
    } catch (e) {
      print('Error adding item to database: $e');
      return 0;
    }
  }

  // Future<int> addItem(ItemModel item) async {
  //   return await db!.transaction((txn) async {
  //     return await txn.insert(
  //       // return db!.insert(
  //       _tableName,
  //       item.toMapForDb(),
  //       conflictAlgorithm: ConflictAlgorithm.ignore,
  //     );
  //   });
  // }
}
// Future<List<int>> fetchTopIds() {
//   // TODO: implement fetchTopIds
//   throw UnimplementedError();
// }

this is the api class

import 'dart:convert';

import 'package:http/http.dart' show Client;
import 'package:new_flutter/src/models/item_model.dart';

const rootDomain = '';

class NewsApiProv2 {
  Client client = Client();

  /// Fetching Top story IDs from the API.......
  Future<List<int>> fetchTopIds() async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/topstories.json'))
          .timeout(const Duration(seconds: 10));

      if (response.statusCode == 200) {
        final ids = json.decode(response.body);

        return ids.cast<int>();
      } else {
        print("Error: Failed to fetch top IDs. Status: ${response.statusCode}");
      }
    } catch (e) {
      print('Exception during fetchTopIds: $e');
    }
    return [];
  }

  /// Fetching a specific Story/ITEM by ID........
  Future<ItemModel?> fetchItem(int id) async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/item/$id.json'))
          .timeout(const Duration(seconds: 10));
      if (response.statusCode == 200) {
        final parsedJson = json.decode(response.body);

        if (parsedJson == null || parsedJson.isEmpty) {
          print('Empty or null response for item with id $id');
          return null;
        }
        return ItemModel.fromJson(parsedJson);
      } else {
        print(
            'Failed to fetch item with id $id, Status Code: ${response.statusCode}');
        throw Exception('Failed to load item');
      }
    } catch (e) {
      print('Exception during fetchItem: $e');
    }
    return null;
  }
}

This is repository class:

import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_api_prov2.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_db_prov_2.dart';

class RepositoryProv2 {
  /// Initialize instances of the providers
  final NewsApiProv2 _newsApiProvider = NewsApiProv2();
  final NewsDbProv2 _newsDbProvider = NewsDbProv2();

  /// Fetch the top story IDs from the API
  Future<List<int>> fetchTopIds() async {
    try {
      return await _newsApiProvider.fetchTopIds();
    } catch (e) {
      print("Error fetching top IDs: $e");
      return [];
    }
  }

  /// Fetch an individual item from either API or Database (cache)
  Future<ItemModel?> fetchItems(int id) async {
    try {
      /// First try fetching the item from the database (cache)
      ItemModel? item = await _newsDbProvider.fetchItem(id);

      /// If the item is not found in the database, fetch from the API
      if (item == null) {
        item = await _newsApiProvider.fetchItem(id);

        /// If the item was found, save it in the database (cache)
        if (item != null) {
          await _newsDbProvider.addItem(item);
        }
      }
      return item;
    } catch (e) {
      print("Error fetching item: $e");
      return null;
    }
  }
}

This is my bloc class:

import 'package:flutter/cupertino.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/repository_prov2.dart';

class NewsBloc extends ChangeNotifier {
  final RepositoryProv2 _prov2 = RepositoryProv2();

  List<int> _topIds = [];
  final List<ItemModel> _items = [];
  bool _isLoading = false;

  List<int> get topIds => _topIds;

  List<ItemModel> get items => _items;

  bool get isLoading => _isLoading;

  ///Fetch Top IDs from the API
  Future<void> fetchTopIds() async {
    _isLoading = true;
    notifyListeners(); //Notify UI to update

    try {
      _topIds = await _prov2.fetchTopIds();
    } catch (e) {
      print('Error fetching top IDs: $e');
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  /// Fetching ITEMS by IDs
  Future<ItemModel?> fetchItem(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      final item = await _prov2.fetchItems(id);
      if (item != null) {
        _items.add(item);
      }
    } catch (e) {
      print('Error fetching item: $e');
    } finally {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _isLoading = false;
        notifyListeners();
      });
    }
    return null;
  }
}

this is the app.dart:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/screens/news_list.dart';
import 'package:provider/provider.dart';

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => NewsBloc(),
      child: MaterialApp(
        title: 'News!',
        home: NewsList(),
      ),
    );
  }
}

this is App.dart

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/widgets/news_list_tile.dart';
import 'package:provider/provider.dart';

class NewsList extends StatelessWidget {
  const NewsList({super.key});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    ///Fetch Top IDs when the screen loads
    if (bloc.topIds.isEmpty) {
      bloc.fetchTopIds();
    }

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.blue,
        elevation: 5,
        title: const Text(
          'Top News',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: buildList(bloc),
    );
  }

  Widget buildList(NewsBloc bloc) {
    return Consumer<NewsBloc>(
      builder: (context, bloc, child) {
        if (bloc.isLoading) {
          return Center(
            child: CircularProgressIndicator(color: Colors.blue),
          );
        }

        return ListView.builder(
          itemCount: bloc.topIds.length,
          itemBuilder: (context, int index) {
            return NewsListTile(
              itemId: bloc.topIds[index],
            );
          },
        );
      },
    );
  }
}

This is news list tile class:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:provider/provider.dart';

import '../blocs/latest_bloc_provider/news_bloc.dart';

class NewsListTile extends StatelessWidget {
  final int? itemId;

  const NewsListTile({super.key, this.itemId});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    return FutureBuilder<ItemModel?>(
      future: bloc.fetchItem(itemId!),
      builder: (context, snapshot) {
        // if (!snapshot.hasData) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Text('Still loading item $itemId');
        }

        if (snapshot.hasError) {
          return Text('Error loading item $itemId: ${snapshot.error}');
        }
        if (!snapshot.hasData) {
          return Text('No data available');
        }
        return Text(snapshot.data!.title);
      },
    );
  }
}

The errors I am receiving from this is confusing and this is it:

======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for NewsBloc:
setState() or markNeedsBuild() called during build.

This _InheritedProviderScope<NewsBloc?> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<NewsBloc?>
  value: Instance of 'NewsBloc'
  listening to value
The widget which was currently being built when the offending call was made was: NewsListTile
  dirty
  dependencies: [_InheritedProviderScope<NewsBloc?>]
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5177:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5189:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:577:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:437:24)
#4      NewsBloc.fetchItem (package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart:36:5)
#5      NewsListTile.build (package:new_flutter/src/widgets/news_list_tile.dart:17:20)
#6      StatelessElement.build (package:flutter/src/widgets/framework.dart:5687:49)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5617:15)
The NewsBloc sending notification was: Instance of 'NewsBloc'
====================================================================================================
D/EGL_emulation(13392): app_time_stats: avg=1797.18ms min=1797.18ms max=1797.18ms count=1
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction

I am trying to create a web blog with Hacker News API, but every time I try to run, I get this confusing error thrown at me and I do not get it. asked chatgpt, it gave me a solution but I still run into the same error. I am pasting all necessary classes.

first this is my database class.

import 'dart:io';

import 'package:new_flutter/src/models/item_model.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

final newsDbProv2 = NewsDbProv2();

class NewsDbProv2 {
  static const _dbName = "items.db";
  static const _dbVersion = 1;
  static const _tableName = "Items";

  Database? db;

  /// INITIALIZING THE DATABASE......
  Future<void> init() async {
    // if (db != null) return;
    if (db == null) {
      try {
        Directory documentsDirectory = await getApplicationDocumentsDirectory();
        final path = join(documentsDirectory.path, _dbName);
        db = await openDatabase(path,
            version: _dbVersion, onCreate: createTable);
      } catch (e) {
        print('Error initializing database: $e');
      }
    }
  }

  ///CREATING THE DATABASE TABLE........
  Future<void> createTable(Database newDb, int version) async {
    try {
      await newDb.execute("""
          CREATE TABLE $_tableName
          (
            id INTEGER PRIMARY KEY,
            type TEXT,
            by TEXT,
            time INTEGER,
            text TEXT,
            parent INTEGER,
            kids BLOB,
            dead INTEGER,
            deleted INTEGER,
            url TEXT,
            score INTEGER,
            title TEXT,
            descendants INTEGER
          )
          """);
    } catch (e) {
      print('Error creating table: $e');
    }
  }

  ///Fetching an ITEM by ID from the DATABASE.....
  Future<ItemModel?> fetchItem(int id) async {
    try {
      if (db == null) await init();

      final maps = await db!.query(
        _tableName,
        columns: null,
        where: "id = ?",
        whereArgs: [id],
      );

      if (maps.isNotEmpty) {
        return ItemModel.fromDB(maps.first);
      }
    } catch (e) {
      print('Error fetching item from the database: $e');
    }
    return null;
  }

  Future<int> addItem(ItemModel item) async {
    try {
      if (db == null) await init();

      return await db!.transaction((txn) async {
        return await txn.insert(
          // return db!.insert(
          _tableName,
          item.toMapForDb(),
          conflictAlgorithm: ConflictAlgorithm.ignore,
        );
      });
    } catch (e) {
      print('Error adding item to database: $e');
      return 0;
    }
  }

  // Future<int> addItem(ItemModel item) async {
  //   return await db!.transaction((txn) async {
  //     return await txn.insert(
  //       // return db!.insert(
  //       _tableName,
  //       item.toMapForDb(),
  //       conflictAlgorithm: ConflictAlgorithm.ignore,
  //     );
  //   });
  // }
}
// Future<List<int>> fetchTopIds() {
//   // TODO: implement fetchTopIds
//   throw UnimplementedError();
// }

this is the api class

import 'dart:convert';

import 'package:http/http.dart' show Client;
import 'package:new_flutter/src/models/item_model.dart';

const rootDomain = 'https://hacker-news.firebaseio/v0';

class NewsApiProv2 {
  Client client = Client();

  /// Fetching Top story IDs from the API.......
  Future<List<int>> fetchTopIds() async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/topstories.json'))
          .timeout(const Duration(seconds: 10));

      if (response.statusCode == 200) {
        final ids = json.decode(response.body);

        return ids.cast<int>();
      } else {
        print("Error: Failed to fetch top IDs. Status: ${response.statusCode}");
      }
    } catch (e) {
      print('Exception during fetchTopIds: $e');
    }
    return [];
  }

  /// Fetching a specific Story/ITEM by ID........
  Future<ItemModel?> fetchItem(int id) async {
    try {
      final response = await client
          .get(Uri.parse('$rootDomain/item/$id.json'))
          .timeout(const Duration(seconds: 10));
      if (response.statusCode == 200) {
        final parsedJson = json.decode(response.body);

        if (parsedJson == null || parsedJson.isEmpty) {
          print('Empty or null response for item with id $id');
          return null;
        }
        return ItemModel.fromJson(parsedJson);
      } else {
        print(
            'Failed to fetch item with id $id, Status Code: ${response.statusCode}');
        throw Exception('Failed to load item');
      }
    } catch (e) {
      print('Exception during fetchItem: $e');
    }
    return null;
  }
}

This is repository class:

import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_api_prov2.dart';
import 'package:new_flutter/src/resources/new_resource_dir/news_db_prov_2.dart';

class RepositoryProv2 {
  /// Initialize instances of the providers
  final NewsApiProv2 _newsApiProvider = NewsApiProv2();
  final NewsDbProv2 _newsDbProvider = NewsDbProv2();

  /// Fetch the top story IDs from the API
  Future<List<int>> fetchTopIds() async {
    try {
      return await _newsApiProvider.fetchTopIds();
    } catch (e) {
      print("Error fetching top IDs: $e");
      return [];
    }
  }

  /// Fetch an individual item from either API or Database (cache)
  Future<ItemModel?> fetchItems(int id) async {
    try {
      /// First try fetching the item from the database (cache)
      ItemModel? item = await _newsDbProvider.fetchItem(id);

      /// If the item is not found in the database, fetch from the API
      if (item == null) {
        item = await _newsApiProvider.fetchItem(id);

        /// If the item was found, save it in the database (cache)
        if (item != null) {
          await _newsDbProvider.addItem(item);
        }
      }
      return item;
    } catch (e) {
      print("Error fetching item: $e");
      return null;
    }
  }
}

This is my bloc class:

import 'package:flutter/cupertino.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:new_flutter/src/resources/new_resource_dir/repository_prov2.dart';

class NewsBloc extends ChangeNotifier {
  final RepositoryProv2 _prov2 = RepositoryProv2();

  List<int> _topIds = [];
  final List<ItemModel> _items = [];
  bool _isLoading = false;

  List<int> get topIds => _topIds;

  List<ItemModel> get items => _items;

  bool get isLoading => _isLoading;

  ///Fetch Top IDs from the API
  Future<void> fetchTopIds() async {
    _isLoading = true;
    notifyListeners(); //Notify UI to update

    try {
      _topIds = await _prov2.fetchTopIds();
    } catch (e) {
      print('Error fetching top IDs: $e');
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  /// Fetching ITEMS by IDs
  Future<ItemModel?> fetchItem(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      final item = await _prov2.fetchItems(id);
      if (item != null) {
        _items.add(item);
      }
    } catch (e) {
      print('Error fetching item: $e');
    } finally {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _isLoading = false;
        notifyListeners();
      });
    }
    return null;
  }
}

this is the app.dart:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/screens/news_list.dart';
import 'package:provider/provider.dart';

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => NewsBloc(),
      child: MaterialApp(
        title: 'News!',
        home: NewsList(),
      ),
    );
  }
}

this is App.dart

import 'package:flutter/material.dart';
import 'package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart';
import 'package:new_flutter/src/widgets/news_list_tile.dart';
import 'package:provider/provider.dart';

class NewsList extends StatelessWidget {
  const NewsList({super.key});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    ///Fetch Top IDs when the screen loads
    if (bloc.topIds.isEmpty) {
      bloc.fetchTopIds();
    }

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.blue,
        elevation: 5,
        title: const Text(
          'Top News',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: buildList(bloc),
    );
  }

  Widget buildList(NewsBloc bloc) {
    return Consumer<NewsBloc>(
      builder: (context, bloc, child) {
        if (bloc.isLoading) {
          return Center(
            child: CircularProgressIndicator(color: Colors.blue),
          );
        }

        return ListView.builder(
          itemCount: bloc.topIds.length,
          itemBuilder: (context, int index) {
            return NewsListTile(
              itemId: bloc.topIds[index],
            );
          },
        );
      },
    );
  }
}

This is news list tile class:

import 'package:flutter/material.dart';
import 'package:new_flutter/src/models/item_model.dart';
import 'package:provider/provider.dart';

import '../blocs/latest_bloc_provider/news_bloc.dart';

class NewsListTile extends StatelessWidget {
  final int? itemId;

  const NewsListTile({super.key, this.itemId});

  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of<NewsBloc>(context);

    return FutureBuilder<ItemModel?>(
      future: bloc.fetchItem(itemId!),
      builder: (context, snapshot) {
        // if (!snapshot.hasData) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Text('Still loading item $itemId');
        }

        if (snapshot.hasError) {
          return Text('Error loading item $itemId: ${snapshot.error}');
        }
        if (!snapshot.hasData) {
          return Text('No data available');
        }
        return Text(snapshot.data!.title);
      },
    );
  }
}

The errors I am receiving from this is confusing and this is it:

======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for NewsBloc:
setState() or markNeedsBuild() called during build.

This _InheritedProviderScope<NewsBloc?> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<NewsBloc?>
  value: Instance of 'NewsBloc'
  listening to value
The widget which was currently being built when the offending call was made was: NewsListTile
  dirty
  dependencies: [_InheritedProviderScope<NewsBloc?>]
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:5177:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5189:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:577:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:437:24)
#4      NewsBloc.fetchItem (package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart:36:5)
#5      NewsListTile.build (package:new_flutter/src/widgets/news_list_tile.dart:17:20)
#6      StatelessElement.build (package:flutter/src/widgets/framework.dart:5687:49)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5617:15)
The NewsBloc sending notification was: Instance of 'NewsBloc'
====================================================================================================
D/EGL_emulation(13392): app_time_stats: avg=1797.18ms min=1797.18ms max=1797.18ms count=1
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
I/flutter (13392): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction
Share Improve this question asked Nov 17, 2024 at 3:31 Fred_WolfeFred_Wolfe 8722 gold badges11 silver badges22 bronze badges 3
  • most likely it happens since you are calling notifyListeners inside fetchItems method: it forces another rebuild while building your NewsListTile – pskink Commented Nov 17, 2024 at 7:46
  • you are saying the same thing ChatGPT said brother. still no fix. What is the way around – Fred_Wolfe Commented Nov 17, 2024 at 8:00
  • I am getting a new error now... or more like a warning: I/flutter (14787): Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction – Fred_Wolfe Commented Nov 17, 2024 at 10:11
Add a comment  | 

1 Answer 1

Reset to default 1

According to

#4 NewsBloc.fetchItem (package:new_flutter/src/blocs/latest_bloc_provider/news_bloc.dart:36:5)

the error occurred in bloc class NewsBloc line 36, wrap notifyListeners() in WidgetsBinding.instance.addPostFrameCallback might solve this problem.

  /// Fetching ITEMS by IDs
  Future<ItemModel?> fetchItem(int id) async {
    _isLoading = true;
    WidgetsBinding.instance.addPostFrameCallback((_) {
      notifyListeners();
    });

    try {
      final item = await _prov2.fetchItems(id);
      if (item != null) {
        _items.add(item);
      }
    } catch (e) {
      print('Error fetching item: $e');
    } finally {
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _isLoading = false;
        notifyListeners();
      });
    }
    return null;
  }

本文标签: