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
|
1 Answer
Reset to default 1According 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
insidefetchItems
method: it forces another rebuild while building yourNewsListTile
– 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
1 Answer
Reset to default 1According 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;
}
本文标签:
版权声明:本文标题:flutter - setState() or markNeedsBuild() called during build. Warning database has been locked for 0:00:10.000000 - Stack Overfl 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745639599a2160661.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
notifyListeners
insidefetchItems
method: it forces another rebuild while building yourNewsListTile
– pskink Commented Nov 17, 2024 at 7:46