Box not found ERROR when calling Hive.openBox() - flutter

Box not found. Did you forget to call Hive.openBox()? is the result of a call to Hive.openBox(). It is shown in the console. However the widget works fine and the contents of the box is shown correctly! I mean I know that the box is NOT open, that's why I open it...
Error message:
======== Exception caught by widgets library =======================================================
The following HiveError was thrown building FutureBuilder<Box<CreditCardOverview>>(dirty, state: _FutureBuilderState<Box<CreditCardOverview>>#d0a4f):
Box not found. Did you forget to call Hive.openBox()?
My flutter code:
// ...
Expanded(
child: FutureBuilder(
future: Hive.openBox<CreditCardOverview>('ccOverview'),
builder: (BuildContext context, AsyncSnapshot snapshot) {
// ... builder function checking snapshot etc.
}
// ....
UPDATE
This is the complete code of the state :
class _FinancialsListSmallState extends State<FinancialsListSmall> {
#override
Widget build(BuildContext context) {
final sizeX = MediaQuery.of(context).size.width;
final sizeY = MediaQuery.of(context).size.height - MediaQuery.of(context).viewInsets.bottom;
return SafeArea(
child: Container(
width: sizeX,
height: sizeY,
child: Column(
children: [
PageTitleSmall(titleText: 'My Credit Cards', leadingIcon: Icon(Icons.credit_card)),
Expanded(
child: FutureBuilder(
future: Hive.openBox<CreditCardOverview>('ccOverview'),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
const Icon(
Icons.check_circle_outline,
color: Colors.green,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Result: ${snapshot.data}'),
)
];
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = const <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return ListView(
children: showCreditCardOverview(),
);
},
),
),
],
),
),
);
}
Any ideal what is going on here?

Open the box in main.dart instead of a particular file.
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
Void main()async{
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
Hive.registerAdapter(TAdapter());
await Hive.openBox<T>('boxName');
}
And now you can use this box in any file you want. For instance :
In example.dart
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
class _ExampleScreenState extends State<ExampleScreen>{
Box<T> boxName = Hive.box<T>('boxName');
#override
Widget build(BuildContext context) {
//your code here
}
}

Related

Listview show nothing with asynchronous method

I don't know why when I build my project, no error are return but my listview is empty..
The class :
final LocationService service = LocationService();
late Future<List<Location>> _locations;
#override
void initState() {
super.initState();
_locations = service.getLocations();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Mes locations'),
),
bottomNavigationBar: const BottomNavBar(2),
body: Center(
child: FutureBuilder<List<Location>>(
future: _locations,
builder:
(BuildContext context, AsyncSnapshot<List<Location>> response) {
List<Widget> children;
if (response.hasData) {
children = <Widget>[
ListView.builder(
itemCount: response.data?.length,
itemBuilder: (context, index) =>
_BuildRow(response.data?[index]),
itemExtent: 285,
),
];
} else if (response.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 40,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Un problème est survenu'),
),
];
} else {
children = const <Widget>[
SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(
strokeWidth: 6,
),
),
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
);
}),
),
);
}
// ignore: non_constant_identifier_names
_BuildRow(Location? location) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
Text(
"OKOK",
style: LocationTextStyle.priceBoldGreyStyle,
),
Text("${location?.dateFin}")
],
),
Text("${location?.montanttotal}€")
],
)
],
);
}
I have print my response.data?.length and it not empty.
At first it gave me the error "has size" but now the debug console is empty too...
You can find my project on GitLab : https://gitlab.com/victor.nardel/trash-project-flutter
Thank you in advance for your help
the error is caused by ListView.builder
simple solution:
wrap your ListView with Expanded
if (response.hasData) {
children = <Widget>[
Expanded(
child:ListView.builder(
....
for better code: just return the Widget, not List of widget.
something like below:
if(hasdata) return Listview();
else if(has error) return Column();
else return CircularIndicator();
so you can avoid redundant Widget.

How to fix Image overflow in Flutter PageView?

I'm building an app where it shows the title, author name, number of upvotes, and an image from the subreddit in a page view. Everything is working fine but for some images, the page view is overflowing, how do I fix this?
Here's the overflow error:
Here's my code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class Stardew extends StatefulWidget {
const Stardew({ Key? key }) : super(key: key);
#override
State<Stardew> createState() => _StardewState();
}
class _StardewState extends State<Stardew> {
List data = [];
Future<String> getData() async {
List temp_data = [];
var response = await http.get(
Uri.parse("https://m...content-available-to-author-only...p.com/gimme/stardewvalley/100")
);
return response.body;
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.data == null){
return Center(child: CircularProgressIndicator(color: Color(0xff008b00)));
}
var jsonData = jsonDecode(snapshot.data);
jsonData = jsonData["memes"];
return PageView.builder(
//scrollDirection: Axis.vertical,
itemCount: jsonData.length,
itemBuilder: (BuildContext context, int index){
return Center(
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
getImgCard(
jsonData[index]["title"],
//jsonData[index]["preview"][2],//preview image
jsonData[index]["url"], //original image
jsonData[index]["author"],
(jsonData[index]["ups"]).toString()
)
],
),
),
);
},
);
}
);
}
Widget getImage(String imgUrl){
return Container(
child: Image.network(
imgUrl,
fit: BoxFit.scaleDown,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded/loadingProgress.expectedTotalBytes! : null,
color: Color(0xff008b00),
),
);
},
),
);
}
Widget getImgCard(String title, String imgUrl, String author, String ups){
return Card(
color: Color(0xff000000),
clipBehavior: Clip.antiAlias,
child: Column(
children: [
ListTile(
leading: RichText(
text: TextSpan(
children: [
TextSpan(
text: ups,
),
const WidgetSpan(
child: Icon(Icons.arrow_upward, size: 18, color: Color(0xff008b00),),
)
],
),
),
title: Text(title, style: TextStyle(color: Colors.white),),
subtitle: Text(
"Posted by u/${author}",
style: TextStyle(color: Colors.white.withOpacity(0.6)),
),
),
getImage(imgUrl),
Padding(padding: EdgeInsets.only(bottom: 8))
],
),
);
}
}
How do I fix this? I have tried changing the box fit and it did not work. Then I used expaned and flexible widgets and still can't find the answer to this solution. please help me.
Wrap getImage(imgUrl) inside Expanded widget.
I found the answer myself, removing the parent column and wrapping it with SingleChildScrollView fixed the error.
return PageView.builder(
//scrollDirection: Axis.vertical,
itemCount: jsonData.length,
itemBuilder: (BuildContext context, int index){
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(1.0),
child: getImgCard(
jsonData[index]["title"],
//jsonData[index]["preview"][2],//preview image
jsonData[index]["url"], //original image
jsonData[index]["author"],
(jsonData[index]["ups"]).toString()
),
)
);
},
);

FutureBuilder shows [instance] instead of actual data

I want to download a list from firestore and display as a list in flutter widget. The data is successfully downloaded (proved by the print(cp.data()).
However, the result shown is [Instance of '_JsonQueryDocumentSnapshot'] instead of the actual carpark data.
Could anyone pls help point out what the bug is.
Thanks
class DownloadDataScreen extends StatefulWidget {
#override
_DownloadDataScreen createState() => _DownloadDataScreen();
}
class _DownloadDataScreen extends State<DownloadDataScreen> {
List<DocumentSnapshot> carparkList = []; //List for storing carparks
void initState() {
super.initState();
readFromFirebase();
}
Future readFromFirebase() async {
// await FirebaseFirestore.instance
await FirebaseFirestore.instance
.collection('carpark')
.get()
.then((QuerySnapshot snapshot) {
snapshot.docs.forEach(
(DocumentSnapshot cp) {
carparkList.add(cp);
print('printing cp');
print(cp.data());
},
);
});
**return carparkList;**
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text(
'Car Park',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: FutureBuilder(
future: readFromFirebase(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
const Icon(
Icons.check_circle_outline,
color: Colors.green,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Column(
children: [
Text('Result: ${snapshot.data}'),
],
),
)
];
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = const <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
},
),
);
}
}
First, you don't need to call the function from the init because you already use the FutureBuilder.
Also, you don't need to cast it because when the future completes, the async snapshot already would provide you a list of DocumentSnapshot in the data and the .doc propertie.
Like this:
FutureBuilder<QuerySnapshot>(
builder:(context,snapshot){
if(snapshot.hasData){
/// here your data
snapshot.data.docs;
}
)

Error calling a widget from one Screen while no erro calling the same widget from another

Getting the following error:
The method '[]' was called on null.
Receiver: null
Tried calling: []("uid")
The relevant error-causing widget was: Container file:///C:/Users/dkasa/Downloads/MICS%20Download/grocery_app/lib/screens/homeScreen.dart:28:14 When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 _VendorCategoriesState.didChangeDependencies (package:grocery_app/widgets/categories_widget.dart:29:88)
#2 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4653:11)
#3 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
The widget below, categories_widget.dart, works when called from vendor_home_screen but gets the error when called from HomeScreen. I am not seeing a difference between the vendor_screen and the HomeScreen as to why the error appears.
categories_widget
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:grocery_app/providers/store_provider.dart';
import 'package:grocery_app/services/product_services.dart';
import 'package:persistent_bottom_nav_bar/persistent-tab-view.dart';
import 'package:grocery_app/screens/product_list_screen.dart';
import 'package:provider/provider.dart';
class VendorCategories extends StatefulWidget {
#override
_VendorCategoriesState createState() => _VendorCategoriesState();
}
class _VendorCategoriesState extends State<VendorCategories> {
ProductServices _services = ProductServices();
List _catList = [];
#override
void didChangeDependencies() {
var _store = Provider.of<StoreProvider>(context);
FirebaseFirestore.instance
.collection('products').where('seller.sellerUid',isEqualTo: _store.storedetails['uid'])
.get()
.then((QuerySnapshot querySnapshot) => {
querySnapshot.docs.forEach((doc) {
//add all this in a list
setState(() {
_catList.add(doc['category']['mainCategory']);
});
}),
});
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
var _storeProvider = Provider.of<StoreProvider>(context);
return FutureBuilder(
future: _services.category.get(),
builder: (BuildContext context,AsyncSnapshot<QuerySnapshot>snapshot){
if(snapshot.hasError){
return Center(child: Text('Something went wrong..'));
}
if(_catList.length==0){
return Center(child: CircularProgressIndicator(),);
}
if(!snapshot.hasData){
return Container();
}
return SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
elevation: 4,
borderRadius: BorderRadius.circular(6),
child: Container(
height: 60,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage('images/background.JPG')
)
),
child: Center(
child: Text('Shop by Category',style: TextStyle(
shadows: <Shadow>[
Shadow(
offset: Offset(2.0,2.0),
blurRadius: 3.0,
color: Colors.black
)
],
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 30
),),
),
),
),
),
Wrap(
direction: Axis.horizontal,
children: snapshot.data.docs.map((DocumentSnapshot document){
return _catList.contains(document.data()['name']) ? //only if _catlList contain the category name from selected vendor
InkWell(
onTap: (){
_storeProvider.selectedCategory(document.data()['name']);
_storeProvider.selectedCategorySub(null);
pushNewScreenWithRouteSettings(
context,
settings: RouteSettings(name: ProductListScreen.id),
screen: ProductListScreen(),
withNavBar: true,
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
},
child: Container(
width: 120,height: 150,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.grey,
width: .5
)
),
child: Column(
children: [
Center(
child: Image.network(document.data()['image']),
),
Padding(
padding: const EdgeInsets.only(left: 8,right: 8),
child: Text(document.data()['name'],textAlign: TextAlign.center,),
),
],
),
),
),
) : Text('');
}).toList(),
),
],
),
);
});
}
}
vendor_home_screen
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:grocery_app/widgets/categories_widget.dart';
import 'package:grocery_app/widgets/vendor_appbar.dart';
import 'package:grocery_app/widgets/vendor_banner.dart';
import 'package:grocery_app/widgets/products/featured_products.dart';
import 'package:grocery_app/widgets/products/best_selling_product.dart';
import 'package:grocery_app/widgets/products/recently_added_products.dart';
class VendorHomeScreen extends StatelessWidget {
static const String id = 'vendor-screen';
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
VendorAppBar(),
];
},
body: ListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [
VendorBanner(),
VendorCategories(),
//Recently Added Products
//Best Selling Products
//Featured Products
RecentlyAddedProducts(),
FeaturedProducts(),
BestSellingProduct()
],
),
),
);
}
}
HomeScreen
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:grocery_app/providers/store_provider.dart';
import 'package:grocery_app/widgets/categories_widget.dart';
import 'package:grocery_app/widgets/image_slider.dart';
import 'package:grocery_app/widgets/my_appbar.dart';
import 'package:grocery_app/widgets/near_by_store.dart';
import 'package:grocery_app/widgets/top_pick_scree.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatelessWidget {
static const String id = 'home-screen';
#override
Widget build(BuildContext context) {
Provider.of<StoreProvider>(context,listen:false);
return Scaffold(
backgroundColor: Colors.grey[200],
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled){
return [
MyAppBar()
];
},
body: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(top: 0.0),
children: [
ImageSlider(),
Container(
color: Colors.white,
child: VendorCategories(),
),
Container(
color: Colors.white,
child: TopPickStore(),
),
Padding(
padding: const EdgeInsets.only(top: 6),
child: NearByStores(),
),
],
),
),
);
}
}
As the Home has already a list, So when adding another list that comes a problem :
body: ListView(
ShrinkWrap: true,
padding: EdgeInsets.only(top: 0.0),
children: [
ImageSlider(),
Container(
color: Colors.white,
child: VendorCategories(),
),
add
sinkWrap :true in your Home Page then Try again hope this will solve your problem .

Disabling FloatingActionButton after list view and showing a message that the limit is exceeded

How can I disable a button, in this case a FAB(Floating Action Button), and prevent the user adding more items to the list because he is exceeding the limit and showing a message? I'm using a FutureBuilder and a ListView.builder, after the user adds 3 item to the list, I want to disable the FAB and prevent the user to add more items to the list and showing some sort of notification/message/floating over button message to the user that he is exceeding the limit of 3 items per list. Here is the code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'screens/add_items_screen.dart';
import 'components/items_list.dart';
class ItemScreen extends StatelessWidget {
static const String id = 'item_screen';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(
color: Colors.grey[600],
),
),
/// I want to disable this button after the limit of 3 items in the list view
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.grey,
child: Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: AddItemScreen(),
)));
},
),
body: SafeArea(
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(20.0),
color: Colors.grey[100],
child: Container(
height: 800,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Item List Display',
style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.w700,
),
),
SizedBox(
height: 20.0,
),
Expanded(
child: Column(
children: [
/// Here is where the items are rendered as a list
Expanded(child: ItemList()),
],
),
),
],
),
),
),
),
),
);
}
}
The Item list component:
import 'package:flutter/material.dart';
import 'common/api/api_caller.dart';
import 'utilities/item_api_helper.dart';
import 'models/item.dart';
import 'stores/item_store.dart';
import 'dart:async';
import 'package:provider/provider.dart';
class ItemList extends StatefulWidget {
#override
_ItemList createState() => _ItemList();
}
class _ItemList extends State<ItemList> {
Future<HTTPResponse<List<ItemData>>> _getItemList() async {
var _itemData = await APICaller.instance.getItems();
var provider = Provider.of<ItemDatStore>(context, listen: false);
provider.setItemList(_itemData.data, notify: false);
return _itemData;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FutureBuilder<HTTPResponse<List<ItemData>>>(
future: _getItemList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Consumer<ItemDataStore>(
builder: (context, itemData, child) {
return ListView.builder(
itemCount: itemData.itemList.length,
itemBuilder: (context, index) {
ItemData items =
itemData.getItemByIndex(index);
return Card(
child: Container(
padding: EdgeInsets.all(10.0),
child: Text('items.title'),
),
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Container();
},
),
),
);
}
}
I've tried using an if statement where I can define if(itemData.itemList.length <3) it should return those three items, else {Text('Item limit of 3 is exceeded')} but I'm not sure if this is the right way or if I defined it right since I put it in the Item List component and I need to put it in the Item Screen. Thanks in advance for you help!
You can wrap your Floating action button with Visibility it hides and not woking anymore :)
Visibility(
visible: items.length > 3,
child : FAB here,
),
You can disable the FAB like this
onPressed: items.length < 3? addItemToList : null;
and addItemToList is
void addItemToList(){
// Do Something here
}