App crashes without any logs when using some plugins to access device Contacts - crash

I want to show contacts in my app for which I tried using contacts_service and contacts_plugin but my app crashes when I run it after installing the packages. I have just imported the file and written no code. I don't see any logs also.
Any other way of integrating contacts in my app would also be of great help!

You really need to learn and master the tools you need to use to develop Flutter applications.
And you really need to explain better your needs when you post a question on SO.
That said I've had a quick try on contacts_plugin and contact_service.
Do not use both, they are made for the same purpose. Choose one or the other.
It seems that contact_service is more stable: a weighted score of 92 over 82.
Android
Trying using contacts_plugin I guess you jad this error:
* What went wrong:
The Android Gradle plugin supports only Kotlin Gradle plugin version 1.2.51 and higher. Project 'contacts_plugin' is using version 1.2.30.
That because the contacts_plugin use kotlin version 1.2.30 and you have AS >= 3.2 like me.
ext.kotlin_version = '1.2.30'.
If you wanna give this a try you can clone the project and include the dependency this way:
contacts_plugin:
path: ../flutter-contacts-plugin/
and change in the plugin build.gradle this line:
ext.kotlin_version = '1.2.30'
with this
ext.kotlin_version = '1.2.51'
Even the iOS Project has problems if you use contact_plugins.
contact_serivce instead it works fine either on Android and on iOS.
Anyway always remember that on Android you need to add this permissions in you AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
and on iOS make sure to set NSContactsUsageDescription in the Info.plist file
<key>NSContactsUsageDescription</key>
<string>This app requires contacts access to function properly.</string>
And create a Flutter project with Swift support.
You can use the default example provided by the contact_service plugin to start learning:
import 'package:flutter/material.dart';
import 'package:contacts_service/contacts_service.dart';
void main() => runApp(ContactsExampleApp());
class ContactsExampleApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(routes: <String, WidgetBuilder>{
'/add': (BuildContext context) => AddContactPage()
}, home: ContactListPage());
}
}
class ContactListPage extends StatefulWidget {
#override
_ContactListPageState createState() => _ContactListPageState();
}
class _ContactListPageState extends State<ContactListPage> {
Iterable<Contact> _contacts;
#override
initState() {
super.initState();
refreshContacts();
}
refreshContacts() async {
var contacts = await ContactsService.getContacts();
setState(() {
_contacts = contacts;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Contacts Plugin Example')),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.of(context).pushNamed("/add").then((_) {
refreshContacts();
});
}),
body: SafeArea(
child: _contacts != null
? ListView.builder(
itemCount: _contacts?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
Contact c = _contacts?.elementAt(index);
return ListTile(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) =>
ContactDetailsPage(c)));
},
leading: (c.avatar != null && c.avatar.length > 0)
? CircleAvatar(backgroundImage: MemoryImage(c.avatar))
: CircleAvatar(
child: Text(c.displayName.length > 1
? c.displayName?.substring(0, 2)
: "")),
title: Text(c.displayName ?? ""),
);
},
)
: Center(child: CircularProgressIndicator()),
),
);
}
}
class ContactDetailsPage extends StatelessWidget {
ContactDetailsPage(this._contact);
final Contact _contact;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:
AppBar(title: Text(_contact.displayName ?? ""), actions: <Widget>[
FlatButton(
child: Icon(Icons.delete),
onPressed: () {
ContactsService.deleteContact(_contact);
})
]),
body: SafeArea(
child: ListView(
children: <Widget>[
ListTile(
title: Text("Name"),
trailing: Text(_contact.givenName ?? "")),
ListTile(
title: Text("Middle name"),
trailing: Text(_contact.middleName ?? "")),
ListTile(
title: Text("Family name"),
trailing: Text(_contact.familyName ?? "")),
ListTile(
title: Text("Prefix"), trailing: Text(_contact.prefix ?? "")),
ListTile(
title: Text("Suffix"), trailing: Text(_contact.suffix ?? "")),
ListTile(
title: Text("Company"),
trailing: Text(_contact.company ?? "")),
ListTile(
title: Text("Job"), trailing: Text(_contact.jobTitle ?? "")),
AddressesTile(_contact.postalAddresses),
ItemsTile("Phones", _contact.phones),
ItemsTile("Emails", _contact.emails)
],
),
));
}
}
class AddressesTile extends StatelessWidget {
AddressesTile(this._addresses);
final Iterable<PostalAddress> _addresses;
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(title: Text("Addresses")),
Column(
children: _addresses
.map((a) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: <Widget>[
ListTile(
title: Text("Street"),
trailing: Text(a.street)),
ListTile(
title: Text("Postcode"),
trailing: Text(a.postcode)),
ListTile(
title: Text("City"), trailing: Text(a.city)),
ListTile(
title: Text("Region"),
trailing: Text(a.region)),
ListTile(
title: Text("Country"),
trailing: Text(a.country)),
],
),
))
.toList())
]);
}
}
class ItemsTile extends StatelessWidget {
ItemsTile(this._title, this._items);
final Iterable<Item> _items;
final String _title;
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(title: Text(_title)),
Column(
children: _items
.map((i) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: ListTile(
title: Text(i.label ?? ""),
trailing: Text(i.value ?? ""))))
.toList())
]);
}
}
class AddContactPage extends StatefulWidget {
#override
State<StatefulWidget> createState() => _AddContactPageState();
}
class _AddContactPageState extends State<AddContactPage> {
Contact contact = Contact();
PostalAddress address = PostalAddress(label: "Home");
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add a contact"),
actions: <Widget>[
FlatButton(
onPressed: () {
_formKey.currentState.save();
contact.postalAddresses = [address];
ContactsService.addContact(contact);
Navigator.of(context).pop();
},
child: Icon(Icons.save, color: Colors.white))
],
),
body: Container(
padding: EdgeInsets.all(12.0),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
decoration: const InputDecoration(labelText: 'First name'),
onSaved: (v) => contact.givenName = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Middle name'),
onSaved: (v) => contact.middleName = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Last name'),
onSaved: (v) => contact.familyName = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Prefix'),
onSaved: (v) => contact.prefix = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Suffix'),
onSaved: (v) => contact.suffix = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Phone'),
onSaved: (v) =>
contact.phones = [Item(label: "mobile", value: v)],
keyboardType: TextInputType.phone),
TextFormField(
decoration: const InputDecoration(labelText: 'E-mail'),
onSaved: (v) =>
contact.emails = [Item(label: "work", value: v)],
keyboardType: TextInputType.emailAddress),
TextFormField(
decoration: const InputDecoration(labelText: 'Company'),
onSaved: (v) => contact.company = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Job'),
onSaved: (v) => contact.jobTitle = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Street'),
onSaved: (v) => address.street = v),
TextFormField(
decoration: const InputDecoration(labelText: 'City'),
onSaved: (v) => address.city = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Region'),
onSaved: (v) => address.region = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Postal code'),
onSaved: (v) => address.postcode = v),
TextFormField(
decoration: const InputDecoration(labelText: 'Country'),
onSaved: (v) => address.country = v),
],
)),
),
);
}
}

Related

The box "name" is already open and of type Box<dynamic>

The error is The box "todo_box" is already open and of type Box.
The relevant error-causing widget was: MyHomePage MyHomePage:file:///D:/Flutter_app/alimi_final/lib/schedule.dart:27:13
When the exception was thrown, this was the stack:
I have no idea about this error.
my code
main.dart
import 'package:hive/hive.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:work_a/map.dart';
import 'package:work_a/schedule.dart';
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
import 'package:work_a/screens/list_screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
//const bool kIsWeb = identical(0, 0.0);
//Future<Box> openHiveBox(todo_box) async {
//if (!kIsWeb && !Hive.isBoxOpen(todo_box))
//Hive.init((await getApplicationDocumentsDirectory()).path);
//return await Hive.openBox(todo_box);
//}
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
final appDocumentDirectory = await getApplicationDocumentsDirectory();
Hive.init(appDocumentDirectory.path);
await Hive.initFlutter();
Hive.registerAdapter(TodoAdapter());
await Hive.openBox('todo_box');
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _alimihomeState();
}
class _alimihomeState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'allimi',
theme: ThemeData(primaryColor: Colors.blue),
home: MyAppBar(),
debugShowCheckedModeBanner: false,
);
}
}
class MyAppBar extends StatelessWidget {
const MyAppBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('알리미'),
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
centerTitle: true,
elevation: 0.0,
),
drawer: Drawer(
child: ListView(
children: [
UserAccountsDrawerHeader(
currentAccountPicture: CircleAvatar(
backgroundImage: AssetImage('images/userimage.jpg'),
),
accountName: Text('한동대생'),
accountEmail: Text('00000000#handong.ac.kr'),
decoration: BoxDecoration(
color: Color.fromRGBO(31, 39, 76, 1.0),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
),
),
),
ListTile(
leading: Icon(
Icons.circle,
color: Colors.black,
size: 10.0,
),
visualDensity: VisualDensity(vertical: -3),
horizontalTitleGap: 1.0,
title: Text('내 스케줄'),
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => schedule()),
);
},
),
SizedBox(
height: 5.0,
),
ListTile(
leading: Icon(
Icons.circle,
color: Colors.black,
size: 10.0,
),
visualDensity: VisualDensity(vertical: -3),
horizontalTitleGap: 1.0,
title: Text('지도 보기'),
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyMap()),
);
},
),
SizedBox(
height: 5.0,
),
ListTile(
leading: Icon(
Icons.circle,
color: Colors.black,
size: 10.0,
),
visualDensity: VisualDensity(vertical: -3),
horizontalTitleGap: 1.0,
title: Text('설정'),
onTap: (){},
),
SizedBox(
height: 295.0,
),
],
),
),
body: Center(
child: Column(
children: [
SizedBox(
height: 70.0,
),
CircleAvatar(
radius: 90.0,
backgroundColor: Colors.white,
backgroundImage: AssetImage('images/logoimage.jpg'),
),
SizedBox(
height: 30.0,
),
Text(
'한동 알리미',
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 210.0,
),
Text(
'DADAEGEEDEUL',
style: TextStyle(
fontSize: 10.0,
),
),
],
),
),
);
}
}
schedule.dart
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
import 'package:work_a/screens/list_screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
// void main() => runApp(MyApp());
//void main() async {
//// hive initialization
//await Hive.initFlutter();
//Hive.registerAdapter(TodoAdapter());
////await Hive.openBox<Todo>(HiveBoxes.todo);
//}
class schedule extends StatelessWidget {
const schedule({Key? key}) : super(key: key);
static final String title = 'Hive Tutorial';
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue
),
home: MyHomePage(
title: '스케줄',
),
);
}
}
list_screen.dart
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
import 'package:work_a/screens/add_todo_Screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Todo Hive Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void dispose() async {
Hive.close();
super.dispose();
//await Hive.openBox<Todo>(HiveBoxes.todo);
//await Hive.openBox<dynamic>('todo_box');
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
title: Text(widget.title),
),
body: ValueListenableBuilder(
valueListenable: Hive.box<Todo>(HiveBoxes.todo).listenable(),
builder: (context, Box<Todo> box, _) {
if (box.values.isEmpty)
return Center(
child: Text("리스트가 비었습니다"),
);
return ListView.builder(
itemCount: box.values.length,
itemBuilder: (context, index) {
Todo? res = box.getAt(index);
return Dismissible(
background: Container(color: Colors.red),
key: UniqueKey(),
onDismissed: (direction) {
res!.delete();
},
child: ListTile(
title: Text(res!.title),
subtitle: Text(res.description),
onTap: () {}),
);
},
);
}),
floatingActionButton: FloatingActionButton(
tooltip: 'Add todo',
child: Icon(Icons.add),
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AddTodoScreen(),
),
),
),
);
}
}
add_todo_screen.dart
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
class AddTodoScreen extends StatefulWidget {
AddTodoScreen({Key? key}) : super(key: key);
#override
_AddTodoScreenState createState() => _AddTodoScreenState();
}
class _AddTodoScreenState extends State<AddTodoScreen> {
//void main() async {
// await Hive.openBox<Todo>(HiveBoxes.todo);
//}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
late String title;
late String description;
validated() {
if (_formKey.currentState != null && _formKey.currentState!.validate()) {
_onFormSubmit();
print("Form Validated");
} else {
print("Form Not Validated");
return;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
title: Text('스케줄 추가'),
),
body: SafeArea(
child: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
autofocus: true,
initialValue: '',
decoration: InputDecoration(
labelText: '스케줄'
),
onChanged: (value) {
setState(() {
title = value;
});
},
validator: (String? value) {
if (value == null || value.trim().length == 0) {
return "required";
}
return null;
},
),
TextFormField(
initialValue: '',
decoration: const InputDecoration(
labelText: '메모',
),
onChanged: (value) {
setState(() {
description = value;
});
},
validator: (String? value) {
if (value == null || value.trim().length == 0) {
return "required";
}
return null;
},
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary:Color.fromRGBO(31, 39, 76, 1.0),
),
onPressed: () {
validated();
},
child: Text('추가'),
)
],
),
),
),
),
);
}
void _onFormSubmit() {
Box<Todo> contactsBox = Hive.box<Todo>(HiveBoxes.todo);
contactsBox.add(Todo(title: title, description: description));
Navigator.of(context).pop();
}
}
ui_test.dart
import 'package:work_a/screens/add_todo_Screen.dart';
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Todo Hive Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
centerTitle: true,
title: Text(widget.title),
),
body: Container(
child: ListView.builder(
itemBuilder: (context, index) {
return Dismissible(
background: Container(color: Colors.red),
key: UniqueKey(),
onDismissed: (direction) {},
child: ListTile(
title: Text('Title'),
subtitle: Text('Description'),
onTap: () {}),
);
},
),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add todo',
child: Icon(Icons.add),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AddTodoScreen(),
),
),
),
);
}
}
boxs.dart
class HiveBoxes {
static String todo = 'todo_box';
}
todo.dart
import 'package:hive/hive.dart';
part 'todo.g.dart';
#HiveType(typeId: 0)
class Todo extends HiveObject {
#HiveField(0)
String? id;
#HiveField(1)
String title;
#HiveField(2)
String description;
Todo({required this.title, required this.description});
}
and
todo.g.dart
I'm assuming that you are saving Todo objects in todo_box.
Change this:
Hive.openBox('todo_box')
and this:
Hive.openBox<dynamic>('todo_box')
to this:
Hive.openBox<Todo>('todo_box')

Flutter Multiple Checkbox From API

I have been able to display Json data from API in FutureBuilder Widget. However, the widget has checkbox for each list. Whenever I check on one list, the whole list get checked.
I want a help on how to check each list individually and be able to use the data of the selected list.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:bottom_navy_bar/bottom_navy_bar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mar/Components/mydrawer.dart';
import 'package:mar/Services/auth.dart';
import 'package:mar/sccreens/readRequirements.dart';
import 'package:mar/sccreens/scanAnalysis.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../constants.dart';
import 'infoAnalysis.dart';
import 'login_screen.dart';
class Know extends StatefulWidget {
static String id = 'Know';
#override
_KnowState createState() => _KnowState();
}
class _KnowState extends State<Know> {
List sympotms = [];
int currentIndex = 2;
bool valuefirst = false;
int _bottomBarIndex = 0;
Auth _auth;
showdialogall(context, String mytitle, String mycontent) {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
title: Text(
mytitle,
style: TextStyle(color: Colors.deepOrange),
),
content: Text(mycontent),
actions: [
Center(
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
color: kMainColor,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ReadReq()),
);
},
child: Text(
"Requirements",
style: TextStyle(color: Colors.black),
)),
),
],
);
});
}
Future fetchdata() async {
var res = await http.get("http://10.0.2.2/medical/symptoms.php");
if (res.statusCode == 200) {
var obj = json.decode(res.body);
return obj;
}
}
bool isSearching = false;
#override
void initState() {
fetchdata().then((data) {
setState(() {
sympotms = data;
});
});
super.initState();
}
void _filterSymptoms(value) {
setState(() {
filteredsympotms = sympotms
.where(
(sym) => sym['name'].toLowerCase().contains(value.toLowerCase()))
.toList();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kMainColor,
title: Text(
"Know Your Analysis",
style: TextStyle(
fontFamily: 'Pacifico',
),
),
actions: <Widget>[
FlatButton(
child: CircleAvatar(
child: Image(
image: AssetImage('images/icons/medical.png'),
),
backgroundColor: Colors.black,
),
onPressed: () {
Navigator.pushNamed(context, Scan.id);
},
),
],
centerTitle: true,
),
drawer: MyDrawer(),
body: Column(
children: [
Expanded(
child: sympotms.length > 0
? ListView.builder(
itemBuilder: (_, index) {
return Container(
child: Row(
children: [
SizedBox(width: 10),
Checkbox(
value: this.valuefirst,
onChanged: (bool value) {
setState(() {
valuefirst = value;
});
},
checkColor: Colors.greenAccent,
activeColor: Colors.black,
),
Text(
"${sympotms[index]['SymptomsName']}",
style: TextStyle(fontSize: 17.0),
),
],
),
);
},
itemCount: sympotms.length,
)
: Container(child: Center(child: Text("Loading..."))),
),
RaisedButton(
child: Text(
" Submit ",
style: TextStyle(fontSize: 20),
),
onPressed: () {
showdialogall(context, "Result !", "CBC Test");
},
// onPressed: showdialogall(context, "Result !", "CBC Test"),
color: Colors.green,
textColor: Colors.white,
splashColor: Colors.grey,
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
),
],
),
//Navigation
bottomNavigationBar: BottomNavyBar(
animationDuration: Duration(milliseconds: 800),
curve: Curves.easeInOut,
selectedIndex: currentIndex,
onItemSelected: (index) async {
if (index == 0) {
Navigator.pushNamed(context, Scan.id);
}
if (index == 1) {
Navigator.pushNamed(context, Information.id);
}
if (index == 2) {
Navigator.pushNamed(context, Know.id);
}
if (index == 3) {
SharedPreferences pref = await SharedPreferences.getInstance();
pref.clear();
await _auth.signOut();
Navigator.popAndPushNamed(context, LoginScreen.id);
}
setState(() {
currentIndex = index;
});
},
items: <BottomNavyBarItem>[
BottomNavyBarItem(
icon: Icon(
Icons.camera_alt,
),
title: Text('Scan'),
activeColor: Colors.black,
inactiveColor: Colors.black,
),
BottomNavyBarItem(
icon: Icon(
Icons.perm_device_information,
),
title: Text('Information'),
activeColor: Colors.black,
inactiveColor: Colors.black,
),
BottomNavyBarItem(
icon: Icon(
Icons.open_in_new_outlined,
),
title: Text('Know analysis'),
activeColor: Colors.black,
inactiveColor: Colors.black,
),
],
),
);
}
}
I want a help on how to check each list individually and be able to use the data of the selected list.
this image display my problem
You can do it by storing the selected index in an array.
Here is the idea.
final selectedIndexes = [];
/// In List View
ListView.builder(
itemBuilder: (_, index) {
return Container(
child: Row(
children: [
SizedBox(width: 10),
Checkbox(
value: selectedIndexes.contains(index),
onChanged: (bool value) {
if(selectedIndexes.contains(index) {
selectedIndexes.remove(index); // unselect
} else {
selectedIndexes.add(index); // select
}
setState(() {});
},
checkColor: Colors.greenAccent,
activeColor: Colors.black,
),
Text(
"${sympotms[index]['SymptomsName']}",
style: TextStyle(fontSize: 17.0),
),
],
),
);
},
itemCount: sympotms.length,
)
Since now you have stored the indexes, you can get whatever data you want for selected checkboxes.

Flutter api reloads every navigation

Whenever I change the page and come back, the api is reloaded. I have tried many suggestions. I would be glad if you help.
Here are the methods I tried :
How to avoid reloading data every time navigating to page
How to parse JSON only once in Flutter
Flutter Switching to Tab Reloads Widgets and runs FutureBuilder
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'models/Word.dart';
class WordListPage extends StatefulWidget {
WordListPage(Key k) : super(key: k);
#override
_WordListPageState createState() => _WordListPageState();
}
class _WordListPageState extends State<WordListPage> {
Future<List<Word>> data;
bool isSearching = false;
TextEditingController myController = TextEditingController();
List<Word> _words = List<Word>();
List<Word> _wordsForDisplay = List<Word>();
var keyListPage = PageStorageKey('list_page_key');
Future<List<Word>> getWord() async {
var response = await http.get("myAPIurl");
var _words = List<Word>();
_words = (json.decode(utf8.decode(response.bodyBytes)) as List)
.map((singleWordMap) => Word.fromJsonMap(singleWordMap))
.toList();
return _words;
}
#override
void initState() {
getWord().then((value) {
setState(() {
_words.addAll(value);
_wordsForDisplay = _words;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: myFutureBuilder(),
appBar: AppBar(
leading: Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: 'Total',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 10,
color: Colors.white,
),
),
TextSpan(
text: '\n${_words.length.toString()}',
style: TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12,
),
),
TextSpan(
text: '\nLetter',
style: TextStyle(
decoration: TextDecoration.none,
color: Colors.white,
fontSize: 10,
),
),
],
),
),
),
centerTitle: true,
title: !isSearching
? Text('My Title')
: TextField(
autofocus: true,
style: TextStyle(color: Colors.white),
controller: myController,
onChanged: (value) {
value = value.toLowerCase();
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(value);
},
).toList();
},
);
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordPronounce = word.pronunciation.toLowerCase();
return wordPronounce.contains(value);
},
).toList();
},
);
},
decoration: InputDecoration(
isCollapsed: true,
icon: Icon(
Icons.menu_book,
color: Colors.white,
),
hintText: 'Search',
hintStyle: TextStyle(color: Colors.white),
),
),
actions: [
isSearching
? IconButton(
icon: Icon(Icons.cancel_outlined),
onPressed: () {
setState(
() {
this.isSearching = false;
myController.clear();
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(wordTitle);
},
).toList();
},
);
},
)
: IconButton(
icon: Icon(Icons.search_sharp),
onPressed: () {
setState(
() {
this.isSearching = true;
},
);
},
),
],
),
);
}
FutureBuilder<List<Word>> myFutureBuilder() {
return FutureBuilder(
future: getWord(),
builder: (context, AsyncSnapshot<List<Word>> snapshot) {
if (snapshot.hasData) {
return myWordListView(snapshot);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
ListView myWordListView(AsyncSnapshot<List<Word>> snapshot) {
return ListView.builder(
itemCount: _wordsForDisplay.length,
itemBuilder: (context, index) {
return ExpansionTile(
title: Text(
_wordsForDisplay[index].word,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0),
),
subtitle: Text(
snapshot.data[index].pronunciation[0].toUpperCase() +
snapshot.data[index].pronunciation.substring(1),
),
leading: CircleAvatar(
child: Text(snapshot.data[index].word[0]),
),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 7.0, horizontal: 19.0),
child: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: snapshot.data[index].word + ' : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(text: snapshot.data[index].meaning),
],
),
),
),
),
],
),
],
);
},
);
}
}
When you navigate and return back, the build method is called. Here you have "myFutureBuilder" placed as the body widget of Scaffold, thus this code get executed, within it "getWord" method is called, an it fetches data from the api everytime.
I suggest you to remove "myFutureBuider" and use "myWirdListView" directly as the body of the scaffold. Change myWordListView(List<Word> listOfWord) to use the word list you have already fetched in the initState() .
You need to to separate your api call from your ui. That way your api will only get called when you want it to. I recommend using some kind of external state management library, such as Provider, BLoC, or RxDart. Flutter will rebuild a widget anytime it wants to, beyond when you trigger it.
you passed getWord() as a function to you future builder so each time the widget get rebuilt, it is called.
To solve that, declare a variable Future<Word> getWordFuture ; , Inside initState assign getWordFuture = getWord(); and use getWordFuture in the Future builder.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'models/Word.dart';
class WordListPage extends StatefulWidget {
WordListPage(Key k) : super(key: k);
#override
_WordListPageState createState() => _WordListPageState();
}
class _WordListPageState extends State<WordListPage> {
Future<List<Word>> data;
bool isSearching = false;
TextEditingController myController = TextEditingController();
List<Word> _words = List<Word>();
List<Word> _wordsForDisplay = List<Word>();
var keyListPage = PageStorageKey('list_page_key');
Future<List<Word>> getWordFuture = Future<List<Word>> ; //1
Future<List<Word>> getWord() async {
var response = await http.get("myAPIurl");
var _words = List<Word>();
_words = (json.decode(utf8.decode(response.bodyBytes)) as List)
.map((singleWordMap) => Word.fromJsonMap(singleWordMap))
.toList();
return _words;
}
#override
void initState() {
getWordFuture = getWord(); //2
getWord().then((value) {
setState(() {
_words.addAll(value);
_wordsForDisplay = _words;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: myFutureBuilder(),
appBar: AppBar(
leading: Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: 'Total',
style: TextStyle(
decoration: TextDecoration.none,
fontSize: 10,
color: Colors.white,
),
),
TextSpan(
text: '\n${_words.length.toString()}',
style: TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12,
),
),
TextSpan(
text: '\nLetter',
style: TextStyle(
decoration: TextDecoration.none,
color: Colors.white,
fontSize: 10,
),
),
],
),
),
),
centerTitle: true,
title: !isSearching
? Text('My Title')
: TextField(
autofocus: true,
style: TextStyle(color: Colors.white),
controller: myController,
onChanged: (value) {
value = value.toLowerCase();
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(value);
},
).toList();
},
);
setState(
() {
_wordsForDisplay = _words.where(
(word) {
var wordPronounce = word.pronunciation.toLowerCase();
return wordPronounce.contains(value);
},
).toList();
},
);
},
decoration: InputDecoration(
isCollapsed: true,
icon: Icon(
Icons.menu_book,
color: Colors.white,
),
hintText: 'Search',
hintStyle: TextStyle(color: Colors.white),
),
),
actions: [
isSearching
? IconButton(
icon: Icon(Icons.cancel_outlined),
onPressed: () {
setState(
() {
this.isSearching = false;
myController.clear();
_wordsForDisplay = _words.where(
(word) {
var wordTitle = word.word.toLowerCase();
return wordTitle.contains(wordTitle);
},
).toList();
},
);
},
)
: IconButton(
icon: Icon(Icons.search_sharp),
onPressed: () {
setState(
() {
this.isSearching = true;
},
);
},
),
],
),
);
}
FutureBuilder<List<Word>> myFutureBuilder() {
return FutureBuilder(
//future: getWord(),
future:getWordFuture,
builder: (context, AsyncSnapshot<List<Word>> snapshot) {
if (snapshot.hasData) {
return myWordListView(snapshot);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
ListView myWordListView(AsyncSnapshot<List<Word>> snapshot) {
return ListView.builder(
itemCount: _wordsForDisplay.length,
itemBuilder: (context, index) {
return ExpansionTile(
title: Text(
_wordsForDisplay[index].word,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0),
),
subtitle: Text(
snapshot.data[index].pronunciation[0].toUpperCase() +
snapshot.data[index].pronunciation.substring(1),
),
leading: CircleAvatar(
child: Text(snapshot.data[index].word[0]),
),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 7.0, horizontal: 19.0),
child: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: snapshot.data[index].word + ' : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(text: snapshot.data[index].meaning),
],
),
),
),
),
],
),
],
);
},
);
}
}

My Content from API is not being shown in Flutter

I wrote my code in flutter, and used NewsAPI.org for getting content about news, such as heading, image, content etc. I made a class "News" and ArticleModel() for retrieving and using the information. I used Conditional Operator (? :) for checking if the data is received, then show it, else CircularProgressIndiactor() is shown. After running the app, CircularProgressIndiactor() shows up and no information is shown/loaded. Can anyone help me here??
No error or warning is shown, and code compiles successfully, but no information is shown up.
Here is the main file, home.dart -
import 'package:flutter/material.dart';
import 'package:news_app/helper/data.dart';
import 'package:news_app/helper/news.dart';
import 'package:news_app/models/article_model.dart';
import 'package:news_app/models/category_models.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<CategoryModel> categories = new List<CategoryModel>();
List<ArticleModel> articles = new List<ArticleModel>();
bool loading = true;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
loading = false;
print('Done');
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Flutter',
style: TextStyle(
color: Colors.black,
),
),
Text(
'News',
style: TextStyle(
color: Colors.blue,
),
),
],
),
//elevation: 2.0,
),
body: loading
? Center(
child: Container(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
///Categories
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
height: 70.0,
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageUrl,
categoryName: categories[index].categoryName,
);
},
),
),
///Blogs
Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageUrl: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
);
},
),
),
],
),
),
),
),
);
}
}
class CategoryTile extends StatelessWidget {
final imageUrl, categoryName;
CategoryTile({this.imageUrl, this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
child: Container(
margin: EdgeInsets.only(right: 16.0),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: Image.network(
imageUrl,
width: 120.0,
height: 160.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
width: 120.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6.0)),
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 14.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageUrl, title, desc;
BlogTile(
{#required this.imageUrl, #required this.desc, #required this.title});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Image.network(imageUrl),
Text(title),
Text(desc),
],
),
);
}
}
Here is the News.dart file -
import 'dart:convert';
import 'package:news_app/models/article_model.dart';
import 'package:http/http.dart' as http;
class News {
List<ArticleModel> news = [];
Future<void> getNews() async{
String url="http://newsapi.org/v2/top-headlines?country=in&category=business&apiKey=xxxxxxxxxxxxxxxxxx";
var response = await http.get(url);
var jsonData = jsonDecode(response.body);
if(jsonData["status"] == "ok") {
jsonData["articles"].forEach((element){
if(element['urlToImage'] != null && element['description'] != null) {
ArticleModel articleModel = ArticleModel(
title: element['title'],
author: element['author'],
description: element['description'],
url: element['url'],
urlToImage: element['urlToImage'],
content: element['content'],
);
news.add(articleModel);
}
});
}
}
}
And at last, ArticleModel.dart -
class ArticleModel {
String author, title, description;
String url, urlToImage;
String content;
ArticleModel({this.title, this.description, this.author, this.content, this.url, this.urlToImage});
}
Updating your request URL from http to https will give you expected result.
Update URL to: "https://newsapi.org/v2/top-headlines?country=in&category=business&apiKey="
Note: Don't share your API key in any open platforms for security reasons.

come from back navigation app not refreshing in flutter

When i am on edit profile screen i changed my details and back from the back icon, On the next screen my updated data not reflecting.
This is my home screen where i need to call below API:
Main.dart
#override
Widget build(BuildContext context) {
return new MaterialApp(
showPerformanceOverlay: false,
debugShowCheckedModeBanner: false,
title: 'hempmeASAP',
home: (is_loggedin) ? Home():Login(),
routes: {
"/home": (_) => new Home(),
"/login": (_) => new Login(),
"/signup": (_) => new Signup(),
"/forgot": (_) => new ForgotPassword()
},
);
}
home.dart
void initState() {
super.initState();
getProfileData();
}
getProfileData() {
customFun.readToken().then((val) {
setState(() {
access_token = val;
});
try{
(() async {
await restApis.getProfile(access_token).then((val) => setState((){
print(val);
name = (val["data"]["name"]).toString();
profile_img = val["data"]["avatarUrl"];
}));
})();
}catch(e){
setState(() {
showProgressBar = false;
//show_error = true;
//error_msg = "The exception thrown is $e";
});
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Text("The exception thrown is $e"),
));
}
});
}
// I need to pass updated name and profile_img here
child: new Scaffold(
key: scaffoldKey,
//drawer: new Drawer(child: DrawerList()),
appBar: AppBarComponent(context: context, appbarTitle:appBarTitle, name: name, profile_img: profile_img),
)
app_bar_component.dart
class AppBarComponent extends AppBar {
AppBarComponent({Key key, BuildContext context, appbarTitle, name, profile_img, screenName})
: super(
key: key,
backgroundColor: Colors.white,
//centerTitle: false,
iconTheme: IconThemeData(
color: Color(0xff888888), //change your color here
),
title: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Stack(
children: <Widget>[
CircleAvatar(
radius: 26.0,
backgroundImage: (profile_img != null && profile_img != "") ? NetworkImage("$profile_img"):NetworkImage('https://via.placeholder.com/150',scale: 1.0),
backgroundColor: Colors.transparent,
),
]
),
Padding(
padding: const EdgeInsets.all(10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 2.0),
child: Text("$name",style: TextStyle(color: Color(0xff444444),fontSize: 16.0))
),
screenName != 'edit' ?
GestureDetector(
child: Text("Edit Profile", style: TextStyle(fontSize: 11.0, color: Colors.blue,decoration: TextDecoration.underline)),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Editprofile())
);
}
):Container()
]
)
)
],
),
),
actions: <Widget>[
new IconButton(
onPressed: () =>
customFun.logout().then((_) =>
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=> Login(logout:true)))
),
icon: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 8.0,top: 4.0),
child: Icon(Icons.exit_to_app,color: Color(0xff888888)),
),
]
)
),
],
);
}
editprofile.dart
void _submitlogin() {
final form = formKey.currentState;
Map _data;
if(form.validate()){
if(_newpassword != _confirmpassword){
setState(() {
show_error = true;
error_msg = "Confirm Password should match password";
});
}
showProgressBar = true;
customFun.readToken().then((val) {
access_token = val;
try{
(() async {
await restApis.postUpdateProfile(access_token,_name,_mobile,_oldpassword,_newpassword,_confirmpassword).then((val) => setState(() {
// print("response");
print(val);
if(val["success"]){
form.save();
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.green,
content: Text(val["message"]),
));
setState(() {
showProgressBar = false;
show_error = false;
});
_getProfleDetail();
}else{
showProgressBar = false;
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Text(val["message"]),
));
}
}));
})();
}catch(e){
setState(() {
showProgressBar = false;
//show_error = true;
//error_msg = "The exception thrown is $e";
});
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Text("The exception thrown is $e"),
));
}
});
}
}
THESE ARE THE MAIN FUNCTIONS AND WHEN I UPDATE MY PROFILE AND BACK FROM NAVIGATION BACK ICON ON EDIT PROFILE SCREEN ON MY HOME PAGE APP BAR PROFILE PHOTO AND THE NAME IS NOT UPDATING. NAME AND PROFILE PHOTO SHOULD BE UPDATED IN APP.
I need to call getProfileData(); function when i am coming to home screen from edit profile screen.
UPDATED: My issue is when i update my image from updateprofile screen this result is not reflecting on the home screen.
Please let me know if any solution.