Riverpood does not update the status until I enter the screen - flutter

I have a general configuration screen, with a button that syncs the data
(...)
appBar: AppBar(
actions: [
Row(
children: [
const Text(ConfigurationsStringsUI.updateGeneral),
IconButton(
icon: const Icon(Icons.sync),
onPressed: () {
ref.read(listProductController.notifier).syncProducts();
ref.read(listEmployedController.notifier).syncEmployees();
},
),
],
)
],
),
(...)
In the case of products, it has a specific screen that is responsible for managing them, basically a CRUD. When I press the sync button, the idea is to connect to supabase and update the data. While this is happening display a loadign. The problem is that the loading does not appear.
products_page.dart
GetIt sl = GetIt.instance;
class CRUDProduct extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
},
),
actions: [
IconButton(
onPressed: () {
ref.read(listProductController.notifier).syncProducts();
},
icon: const Icon(Icons.update),
)
],
),
floatingActionButton: ref.watch(isVisibleFabProducts)
? FloatingActionButton(
onPressed: () {
showDialog(
context: scaffoldKey.currentContext!,
builder: (context) => AddProductDialog(),
);
},
child: const Icon(Icons.fastfood),
)
: null,
body: ref.watch(listProductController).when(
data: (products) {
if (products.isEmpty) {
return const Center(
child: Text(ProductStringsUI.emptyList),
);
} else {
return NotificationListener<UserScrollNotification>(
onNotification: (notification) {
if (notification.direction == ScrollDirection.forward) {
ref.read(isVisibleFabProducts.notifier).state = true;
}
if (notification.direction == ScrollDirection.reverse) {
ref.read(isVisibleFabProducts.notifier).state = false;
}
return true;
},
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) {
return ItemProductList(product: products[index]);
},
separatorBuilder: (_, __) => const Divider(
color: Colors.grey,
),
itemCount: products.length),
);
}
},
error: (error, stackTrace) {
return const Center(
child: Text(ProductStringsUI.errorList),
);
},
loading: () {
return const Center(child: CircularProgressIndicator());
},
));
}
}
Product provider:
final listProductController =
StateNotifierProvider<ProductController, AsyncValue<List<LocalProduct>>>(
(ref) => ProductController(ref));
product_controller.dart
class ProductController extends StateNotifier<AsyncValue<List<LocalProduct>>> {
ProductController(this._ref) : super(const AsyncValue.loading()) {
getProducts();
}
final Ref _ref;
Future<void> getProducts() async {
try {
final employees = await sl.get<ListProductUseCase>().getProducts();
if (mounted) {
state = AsyncValue.data(employees);
}
} catch (e) {
state = AsyncValue.error(e, StackTrace.current);
}
}
Future<void> syncProducts() async {
try {
_ref.read(listCategoryController.notifier).state =
const AsyncValue.loading();
_ref.read(listEmployedController.notifier).state =
const AsyncValue.loading();
state = const AsyncValue.loading();
await _ref.read(listCategoryController.notifier).syncCategory();
final employees = await sl.get<SyncProductUseCase>().syncProducts();
state.whenData((value) {
if (mounted) {
state = AsyncValue.data([...value, ...employees]);
}
});
_ref.invalidate(listProductController);
} catch (e) {
state = AsyncValue.error(e, StackTrace.current);
}
}
}
In the case of products, it has a specific screen that is responsible for managing them, basically a CRUD. When I press the sync button, the idea is to connect to supabase and update the data. While this is happening display a loadign. The problem is that the loading does not appear. There are two scenarios:
1-I open the app, I press the sync button on the configuration screen, I enter the screen in charge of managing the products, I see the loaded products, and at the moment it updates me with the new data, when I should see the loading and then the new ones data.
In this scenario is where my biggest doubt about the strange behavior is.
2-I open the app, I enter the screen in charge of managing the products, I go to the configuration screen, I press sync, and in that case if I go to enter if the loading appears
The same goes for employees.

When you have an async provider in Riverpod, you should tell it to load:
Future<void> addTopic(String name) async {
state = const AsyncValue.loading(); // Here
state = await AsyncValue.guard(() async { // And then you guard the value
// Inside the brackets do all the logic of the function
final currentId = ref.watch(currentSubjectProvider);
final topicRepo = ref.watch(topicRepoProvider);
await topicRepo.addTopic(currentId!, name);
return _getTopics();
});
}
This example of mine, is a real project I am working on, and this is loading as expected, but I should mention that I am using the Riverpod generator, so if the generator did something, I am unaware of it.
If you set the state to loading and guard the value, all listerners of that provider should be loading correctly.

Related

Flutter: My notifyListeners() doesn't work, but only in the release apk

I have a page that shows a loading while making my API call, and once the call is done it shows the received data.
On debugger everything works correctly, but when I create the apk with 'flutter build apk', and download it, the loading remains indefinitely.
I also put a showDialog at the end of my Provider function that makes the API call (I put this showDialog just below notifyListeners().
I can't understand why in debug it works and in release it doesn't.
(This notifyListeners thing not working just does it for every API call I make)
This is the code of the provider function that makes the api call:
Future<void> getUserSites(context) async {
_userSites.clear();
isLoading = true;
notifyListeners();
try {
final response = await NetworkService.call(
url: '/api/structure/Sites',
method: Method.Get,
context: context) as List<dynamic>;
for (var i = 0; i < response.length; i++) {
_userSites.add(Sites.fromJson(response.elementAt(i)));
}
if (defaultSite == null) {
if (SimplePreferences.getDefaultSite() == null) {
defaultSite = _userSites.isNotEmpty ? _userSites.first : null;
if (defaultSite != null) {
SimplePreferences.setDefaultSite(defaultSite!.id);
}
} else {
defaultSite = _userSites.firstWhere(
(element) => element.id == SimplePreferences.getDefaultSite()!);
}
}
} catch (e) {
inspect(e);
if (SimplePreferences.getToken() != null) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('General Error'),
content: Text(e.toString()),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'Ok',
),
)
],
),
);
}
// throw e;
}
isLoading = false;
notifyListeners();
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('getUserSites done!'),
content: Text(_userSites.toString()),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'Ok',
),
)
],
),
);
}
this is the Home page code:
class HomePageScreen extends StatelessWidget { const HomePageScreen({super.key}); static const String routeName = '/';
#override Widget build(BuildContext context) { log('New Page: Home Page'); final provider = Provider.of<MyManager>(context);
return provider.isLoading ? const Center(
child: CircularProgressIndicator(),
)
: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MainButton(
onTap: () async {
Navigator.of(context)
.pushNamed(ShowPatrolScreen.routeName);
await provider.getPatrol(context);
},
icon: Icons.home,
title: 'ShowPatrol',
),
printSito(provider.defaultSite?.description ?? 'Nessun Sito', context),
PrintRequestZ(
showCompleted: false,
),
],
),
),
);
}
Widget printSito(String name, context) { .... //pass context for Navigator and Theme } } `
this is the main page:
...
final myScreens = [
const HomePageScreen(),
...
];
#override
void initState() {
// TODO: implement initState
super.initState();
print('token: ${SimplePreferences.getToken()}');
if (SimplePreferences.getToken() == null){
Navigator.of(context).pushReplacementNamed('/Auth');
}
var provider = Provider.of<MyManager>(context, listen: false);
provider.setAll(context); //this function calls all my API calls, but for testing, I commented out all other functions and kept only the one written above
}
#override
Widget build(BuildContext context) {
var provider = Provider.of<MyManager>(context);
return Scaffold(
appBar: const MyAppBar(title: 'Ronda',canGoBack: false,),
body: myScreens[currentPage],
bottomNavigationBar: ...
),
}
Thanks in advance!
after some research i found the solution.
You have to use WidgetsBinding.instance.addPostFrameCallback
in the parent component.
So my home page now looks like this:
#override
void initState() {
// TODO: implement initState
super.initState();
print('token: ${SimplePreferences.getToken()}');
if (SimplePreferences.getToken() == null){
Navigator.of(context).pushReplacementNamed('/Auth');
}
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
var provider = Provider.of<MyManager>(context, listen: false);
provider.setAll(context); //this function calls all my API calls, but for testing, I commented out all other functions and kept only the one written above
});
}
I don't quite understand why though. If someone could explain it to me, I'd be very happy
Use Consumer to access the Provider's Variable
return Consumer<YourProviderName>(builder : (context, value, child){
return value.isLoading? const Center(
child: CircularProgressIndicator(),
):YourWidget(),
});

flutter api returning data but its not workin in listviewbuilder

I'm tryig to solve an error in flutter list view builder once im calling my api functions its showing me the exact data i want, but when im giving the variable to listview builder it showing null value on that variable.
// import 'package:asanhisab/models/ledger_model.dart';
import 'package:asanhisab/utils/helper.dart';
import 'package:flutter/material.dart';
import 'package:odoo_api/odoo_api.dart';
import 'package:asanhisab/services/remoteservices.dart';
class GeneralLedgerScreen extends StatefulWidget {
const GeneralLedgerScreen({Key? key}) : super(key: key);
#override
State<GeneralLedgerScreen> createState() => _GeneralLedgerScreenState();
}
class _GeneralLedgerScreenState extends State<GeneralLedgerScreen> {
List? ledger;
bool isloaded = false;
#override
void initState() {
super.initState();
getLedgerData();
}
getLedgerData() async {
var ledger = await RemoteServices().getLedgerData();
if (ledger != null) {
setState(() {
isloaded = true;
});
}
logger.d(ledger.length);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('General Ledger'),
),
body: Scrollbar(
// child: Center(child: CircularProgressIndicator()),
child: Center(
child: Visibility(
visible: isloaded,
// ignore: sort_child_properties_last
child: ListView.builder(
itemCount: ledger?.length,
itemBuilder: (context, index) {
logger.d(ledger);
return Card(
child: ListTile(
leading: const Icon(Icons.payment),
title: Text(index.toString()),
subtitle: const Text('Name'),
iconColor: Colors.blue,
isThreeLine: true,
trailing: const Text('1000'),
onTap: () {},
),
);
},
),
replacement: const CircularProgressIndicator(),
),
),
),
floatingActionButton: FloatingActionButton.extended(
label: const Text('Create'),
icon: const Icon(Icons.add),
backgroundColor: Colors.blue,
onPressed: () {
// Get.to(() => const CreateAccountHead());
},
),
);
}
}
getLedgerData() async {
var client = OdooClient(storage.read('link'));
var authres = await client.authenticate(storage.read('email'),
storage.read('password'), storage.read('dbname'));
if (authres.isSuccess) {
var data = await client
.callKW('ah_general_ledger.ah_account_head', 'search_read', []);
if (data.getStatusCode() == 200) {
return data.getResult();
} else {
logger.d('Error Occured while fetching data');
// errorAlert(context, 'Error Occured while fetching data');
}
} else {
logger.d('Error Occured');
// errorAlert(context, 'Error Occured');
}
return null;
}
I'm tryig to solve an error in flutter list view builder once im calling my api functions its showing me the exact data i want, but when im giving the variable to listview builder it showing null value on that variable.
This is because your are redefined ledger in getLedgerData(), you should use your attribute instead.
getLedgerData() async {
ledger = await RemoteServices().getLedgerData(); // remove var here at the beginning
if (ledger != null) {
setState(() {
isloaded = true;
});
}
logger.d(ledger.length);
}
You can also use private field for your ledger and isloaded by adding _ caracter as prefix.

How To implement appbar Search with provider api in flutter

I'm getting all the users from API and showing it on a list view. what I need to do is when I search for a specific username, then it needs to show a list tile of users that match the same name .after that when I click that username in the search list view I need to show the user profile of that user which I need user-id
I already used showSearch(context: context, delegate: CustomSearchDelegate());
and I fail
this is my UserList Api Class
class GetSharedPatientList with ChangeNotifier {
Future<List<Content>> fetchPatientList(
BuildContext context,
) async {
final bool isConnected = await InternetConnectionChecker().hasConnection;
final prefs = await SharedPreferences.getInstance();
var uuid = prefs.getString("userId");
final bool session = await Session.sessionValid(context);
if (isConnected) {
if (session) {
try {
final response =
await http.get(Uri.parse('$baseUrl/profile_shares?uuid=$uuid'));
if (response.statusCode == 200) {
List jsonResponse = json.decode(response.body)['content'];
print(jsonResponse);
return jsonResponse.map((data) => Content.fromJson(data)).toList();
} else {
throw Exception('Unexpected error occured!');
}
} catch (e) {
Logger().e(e);
}
} else {}
} else {
Alert(
context: context,
type: AlertType.error,
title: "No Internet",
desc: "Please Check Your Internet Connection",
buttons: [
DialogButton(
onPressed: () => Navigator.pop(context),
color: green,
child: const Text(
"Ok",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
}
throw Exception('Failed to load user');
}
}
CustomSearchDelegate Class
class CustomSearchDelegate extends SearchDelegate {
getList(BuildContext context) async {
List<Content> data = await Provider.of<GetSharedPatientList>(context)
.fetchPatientList(context);
return data;
}
// first overwrite to
// clear the search text
#override
List<Widget>? buildActions(BuildContext context) {
return [
IconButton(
onPressed: () {
query = '';
},
icon: const Icon(Icons.clear),
),
];
}
// second overwrite to pop out of search menu
#override
Widget? buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
close(context, null);
},
icon: const Icon(Icons.arrow_back),
);
}
// third overwrite to show query result
#override
Widget buildResults(BuildContext context) {
List<Content> matchQuery = getList(context);
for (var pateint in matchQuery) {
if (pateint.recipientName!.contains(query.toLowerCase())) {
matchQuery.add(pateint);
}
}
return ListView.builder(
itemCount: matchQuery.length,
itemBuilder: (context, index) {
return ProfileList(
patientid: matchQuery[index].senderId.toString(),
username: matchQuery[index].senderName.toString(),
phn: matchQuery[index].phn.toString(),
sharedDate: matchQuery[index].sharedDate.toString(),
);
},
);
}
// last overwrite to show the
// querying process at the runtime
#override
Widget buildSuggestions(BuildContext context) {
List<Content> matchQuery = getList(context);
for (var pateint in matchQuery) {
if (pateint.recipientName!.toLowerCase().contains(query.toLowerCase())) {
matchQuery.add(pateint);
}
}
return ListView.builder(
itemCount: matchQuery.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
UtilFunctions.navigateTo(context,
MainScreen(patientid: matchQuery[index].senderId.toString()));
},
child: ProfileList(
patientid: matchQuery[index].senderId.toString(),
username: matchQuery[index].senderName.toString(),
phn: matchQuery[index].phn.toString(),
sharedDate: matchQuery[index].sharedDate.toString(),
));
},
);
}
}
When I run this I'm getting _TypeError (type 'Future<dynamic>' is not a subtype of type 'List<Content>')
Any Help is much appreciated

Assume a list is being assigned the query of a SQLite database, how to ensure that the list is not null? Flutter

I am making a Flutter application with SQLite database in it with the sqflite package. I have a database helper class with the necessary methods. In one of the pages I want to display the data as a list of cards. I also have an image stored to the database, as such in the same page I have to convert the image back to a File. In the class of that page, named DataPage, I made a method called query which calls the query method of the database and assigns that value to a list called listLokasi. I also made a method called convert which calls List.generate with one of the arguments being listLokasi.length. Meanwhile I placed these 2 methods inside the constructor for _DataPageState as DataPage is a stateful widget. The problem is when I run the app an error displayed showing a NoSuchMethodError as I tried to call length on null, this means listLokasi is null. So I placed asserts in the query method, in the constructor after the query method, and in the convert method. The results is the assert in the query method did not fire, while the assert in the constructor immediately fired. I have inspected my database helper class and reviewed my code and I cannot find the flaw in my code. Any help in this problem would be appreciated. I shall display the code below.
This is the database helper class.
class DatabaseHelper {
static final _instance = DatabaseHelper._internal();
DatabaseHelper._internal();
factory DatabaseHelper() {
return _instance;
}
Database db;
Future initDatabase() async {
var databasePath = await getDatabasesPath();
var path = join(databasePath, 'table.db');
db = await openDatabase(path, version: 1, onCreate: onCreate);
}
onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE lokasi
(id INTEGER PRIMARY KEY,
name TEXT,
description TEXT,
category TEXT,
latitude REAL,
longitude REAL,
image BLOB)
''');
}
Future<Lokasi> insert(Lokasi lokasi) async {
await db.insert('lokasi', lokasi.toJson());
return lokasi;
}
Future<List<Lokasi>> query() async {
var list = await db.query('lokasi');
return List.generate(list.length, (i) => Lokasi.fromJson(list[i]));
}
}
This is the DataPage class.
class DataPage extends StatefulWidget {
final savedUsername;
const DataPage({this.savedUsername = 'User'});
#override
_DataPageState createState() => _DataPageState();
}
class _DataPageState extends State<DataPage> {
DatabaseHelper db = DatabaseHelper();
List<Lokasi> listLokasi;
List<LokasiConvert> listLokasiConvert;
_DataPageState() {
query();
assert(listLokasi != null);
convert();
}
convert() {
assert(listLokasi != null);
listLokasiConvert = List.generate(
listLokasi.length,
(i) => LokasiConvert(
name: listLokasi[i].name,
description: listLokasi[i].category,
category: listLokasi[i].category,
latitude: listLokasi[i].latitude,
longitude: listLokasi[i].longitude,
image: File.fromRawPath(listLokasi[i].image),
),
);
}
Future<List<Lokasi>> query() async {
listLokasi = await db.query();
assert(listLokasi != null);
return listLokasi;
}
void sendUsername(BuildContext context) {
String username = widget.savedUsername;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MainPage(username: username),
),
);
}
void sendUsernameToChart(BuildContext context) {
String chartUsername = widget.savedUsername;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChartPage(savedUsername: chartUsername),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text('Data'),
actions: [
RaisedButton(
child: Text('Logout'),
onPressed: () {
Navigator.popUntil(context, ModalRoute.withName('/'));
},
),
RaisedButton(
child: Text('Main'),
onPressed: () {
sendUsername(context);
},
),
RaisedButton(
child: Text('Charts'),
onPressed: () {
sendUsernameToChart(context);
},
),
],
),
body: ListView.builder(
itemBuilder: (context, i) {
return Card(
child: Row(
children: [
Image.file(
listLokasiConvert[i].image,
width: 100,
height: 100,
),
Column(
children: [
Text(listLokasiConvert[i].name),
Text(listLokasiConvert[i].category),
Text(listLokasiConvert[i].description),
Text('Coordinates: ' +
listLokasiConvert[i].latitude.toString() +
', ' +
listLokasiConvert[i].longitude.toString()),
],
)
],
));
},
itemCount: listLokasiConvert.length,
),
);
}
}
Once again, thank you for any help given.
Maybe you can try this. Hope its help you.
db.query().then((value) {
setState(() {
listLokasi = value
});
});
The solution is actually simple as I discovered in my process. The list is a future so I am supposed to use a future builder and then wrap the listview builder with the future builder. Let me show my finished code of that specific page.
class DataPage extends StatefulWidget {
final savedUsername;
const DataPage({this.savedUsername = 'User'});
#override
_DataPageState createState() => _DataPageState();
}
class _DataPageState extends State<DataPage> {
DatabaseHelper db = DatabaseHelper();
List<Lokasi> listLokasi;
delete(value) async {
await db.delete(value);
}
Future<List<Lokasi>> query() async {
listLokasi = await db.query();
return listLokasi;
}
void sendUsername(BuildContext context) {
String username = widget.savedUsername;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MainPage(username: username),
),
);
}
void sendUsernameToChart(BuildContext context) {
String chartUsername = widget.savedUsername;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChartPage(savedUsername: chartUsername),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text('Data'),
actions: [
RaisedButton(
child: Text('Logout'),
onPressed: () {
Navigator.popUntil(context, ModalRoute.withName('/'));
},
),
RaisedButton(
child: Text('Main'),
onPressed: () {
sendUsername(context);
},
),
RaisedButton(
child: Text('Charts'),
onPressed: () {
sendUsernameToChart(context);
},
),
],
),
body: FutureBuilder(
future: query(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemBuilder: (context, i) {
return Card(
child: Row(
children: [
Column(
children: [
Text(snapshot.data[i].name),
Text(snapshot.data[i].category),
Text(snapshot.data[i].description),
Text('Coordinates: ' +
snapshot.data[i].latitude.toString() +
', ' +
snapshot.data[i].longitude.toString()),
],
),
Container(
width: 100,
height: 100,
child: Image.memory(snapshot.data[i].image),
),
Container(
width: 30,
height: 30,
child: IconButton(
onPressed: () {
db.delete(snapshot.data[i].name);
setState(() {});
},
icon: Icon(Icons.delete, size: 30),
iconSize: 30,
),
)
],
),
);
},
itemCount: snapshot.data.length,
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
}

Flutter, set state() from parent widget called by not rendering

I have three screen.
Home screen. 2 Mortgage Screen. 3. New branch Screen. [Each Mortgage can have one or more branches]
The home screen shows a list of all current mortgages a user ended, with a summary of each the branches in each mortgages.
When the user clicks on one of the mortgages in the list in screen 1, he gets to screen 2 which shows all the details of the branches of that mortgage. User can add new branch by clicking floating action button, to get to page 3.
In page 3, the user fills out a form to add a new branch. Once a branch is added, page 3 is popped, and page 2 is still appearing.
When page 3 is done, a new branch is added to the selected mortgage, and it is supposed to update the data displayed in page 2 and in page 1. I have done this by passing callback methods into pages 2 and 1, and then calling set state in both classes.
Page 2 is updated and displays fine. However, when I go back from page 2 to page 1, page 1 has not updated. Even though the setState method is called in page 1.
I hope its clear, I will add the code of page 1, and maybe you can help me see why the page is not rerendering.
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<MaslulModel> savedMaslulim = <MaslulModel>[];
List<MortgageModel> savedMortgages = <MortgageModel>[];
// THIS METHOD IS CALLED FROM PAGE 2.
notifyHomeScreen() async {
print('2124: notifyHomeScreen called in home_screen');
savedMaslulim.clear();
savedMortgages.clear();
savedMaslulim = await SharedPrefsMethods.getMaslulListFromPrefs();
for (var i = 0; i < savedMaslulim.length; i++) {
print(savedMaslulim[i].getDetails());
}
savedMortgages = sortOutMaslulimToMortgages(savedMaslulim);
setState(() {
print('2124: Set state. Maslul at 0 List size: ${savedMortgages[0].maslulList.length}');
});
}
TextEditingController _textFieldController = TextEditingController();
String codeDialog = '';
String valueText = '';
#override
initState() {
super.initState();
print('InitState');
asyncGetSavedMortgages();
}
void asyncGetSavedMortgages() async {
savedMaslulim = await SharedPrefsMethods.getMaslulListFromPrefs();
savedMortgages = sortOutMaslulimToMortgages(savedMaslulim);
print(savedMortgages.length);
setState(() {
print('Set state called');
});
}
#override
Widget build(BuildContext context) {
for (var i = 0; i < savedMortgages.length; i++) {
if(savedMortgages[i].name=='tonight'){
print('2124: From HOME: ${savedMortgages[i].maslulList.length}');
}
}
return Scaffold(
appBar: AppBar(title: Text(AppLocalizations.of(context)!.translate('my_mortgages'))),
drawer: MainDrawer(),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
// Navigator.pushNamed(context, '/new_mortgage_screen');
_displayTextInputDialog(context);
},
label: Text('הוסף משכנתא'),
icon: Icon(Icons.add),
backgroundColor: Colors.pink,
),
body: ListView.builder(
itemCount: savedMortgages.length,
key: Key(savedMortgages.length.toString()),
itemBuilder: (context, index){
for (var i = 0; i < savedMortgages.length; i++) {
if(savedMortgages[i].name=='tonight'){
print('2124: From HOME itemBuilder: ${savedMortgages[i].maslulList.length}');
}
}
return MortgageSummaryWidget(savedMortgages[index], notifyHomeScreen: notifyHomeScreen );
},
),
);
}
Future<void> _displayTextInputDialog(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('הכנס שם של המשנכתא:'),
content: TextField(
onChanged: (value) {
setState(() {
valueText = value;
});
},
controller: _textFieldController,
decoration: InputDecoration(hintText: "שם"),
),
actions: <Widget>[
FlatButton(
color: Colors.white,
textColor: Colors.red,
child: Text('בטל'),
onPressed: () {
setState(() {
Navigator.pop(context);
});
},
),
FlatButton(
color: Colors.blue,
textColor: Colors.white,
child: Text('בצע'),
onPressed: () {
setState(() {
codeDialog = valueText;
if(codeDialog.isEmpty){
showAlertDialog(context, 'שגיאה', 'לא הכנסת שם מסלול');
return;
}
Navigator.pop(context);
// Navigator.pushNamed(context, '/new_mortgage_screen');
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => NewMortgageScreen(notifyParent: notifyHomeScreen, title: codeDialog,)));
// Navigator.pushNamed(
// context,
// '/new_mortgage_screen',
// arguments: {'mortgageName': codeDialog}
// );
});
},
),
],
);
});
}
}
All the values are updated, but the screen display isn't.
I cannot figure this out. Thanks
I realised the problem, I was sending a parameter into the State, and this wan't getting updated. I changed it to get the parameter by using widget.parameter.