Assigning the sharedPreference value to a variable within the build - flutter

I have successfully stored a value as a string in the localStorage as below:
var acceptedCompany = jsonEncode('${item.company!.name!}');
print('storedCompany: $acceptedCompany'); // succesfully prints value as 'abc'
await sharedPref.save('savedCompany', acceptedCompany);
And now I want to read the stored value from another screen and assign it to a variable which I can then bind to my Text() widget. I have successfully accessed the value within my console. However when I try to assign the stored value to a variable, I get an error:
"Instance of Future<dynamic>"
Here is how am getting back the stored value:
class _SideBarState extends State < SideBar > {
SharedPref sharedPref = SharedPref();
var savedCompany;
String key = 'storedCompany';
#override
#override
void didChangeDependencies() {
getCompany();
super.didChangeDependencies();
}
getCompany() async {
savedCompany = await sharedPref.read(key);
print('getComp: $savedCompany'); // this returns the stored value i.e 'abc' but I can't assign this to the Text widget
}
#override
Widget build(BuildContext context) {
var savedCompany2 = getCompany();
print('getComp2: $savedCompany2'.toString()); // generates an error 'Instance of Future<dynamic>'
return Text($savedCompany2);
}
}
My SharedPref Class looks like this:
read(key) async {
final prefs = await SharedPreferences.getInstance();
final value = prefs.getString(key) ? ? 0;
// print('retrievedValue: ' + '$value');
return value;
}
save(key, value) async {
final prefs = await SharedPreferences.getInstance();
// prefs.setString(key, json.encode(value));
prefs.setString(key, value);
// print('savedToken:' + '$key');
}
How can I access the sharedPreference value and assign it to the variable that I can then bind to the Text widget?

To overcome the problem, you can either set the value after the initState or using FutureBuilder.
FutureBuilder:
class SideBar extends StatefulWidget {
const SideBar({Key? key}) : super(key: key);
#override
State<SideBar> createState() => _SideBarState();
}
class _SideBarState extends State<SideBar> {
SharedPref sharedPref = SharedPref();
String key = 'storedCompany';
Future<String> getCompany() async {
return await sharedPref.read(key);
}
#override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getCompany(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text('Result: ${snapshot.data}');
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Center(child: CircularProgressIndicator());
}
},
);
}
}
After initState():
class SideBar extends StatefulWidget {
const SideBar({Key? key}) : super(key: key);
#override
State<SideBar> createState() => _SideBarState();
}
class _SideBarState extends State<SideBar> {
SharedPref sharedPref = SharedPref();
String key = 'storedCompany';
String? _companyName;
Future<void> getCompany() async {
var name = await sharedPref.read(key);
setState(() {
_companyName = name;
});
}
#override
void initState() {
super.initState();
getCompany();
}
#override
Widget build(BuildContext context) {
if(_companyName == null) return Center(child:CircularProgressIndicator());
return Text(_companyName!);
}
}

Related

Flutter Custom State Management

What I am trying to achieve is a small custom state management solution that I believe is powerful enough to run small and large apps. The core is based on the ValueNotifier and ValueListenable concepts in flutter. The data can be accessed anywhere in the app with out context since I am storing the data like this:
class UserData {
static ValueNotifier<DataLoader<User>> userData =
ValueNotifier(DataLoader<User>());
static Future<User> loadUserData() async {
await Future.delayed(const Duration(seconds: 3));
User user = User();
user.age = 23;
user.family = 'Naoushy';
user.name = 'Anass';
return user;
}
}
So by using UserData.userData you can use the data of the user whenever you want. Everything works fine until I encountered a problem of providing a child to my custom data consumer that rebuilds the widget when there is a new event fired. The DataLoader class looks like this:
enum Status { none, hasError, loading, loaded }
class DataLoader<T> {
Status status = Status.none;
T? data;
Object? error;
bool get hasError => error != null;
bool get hasData => data != null;
}
which is very simple. Now the class for consuming the data and rebuilding looks like this:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:testing/utils/dataLoader/data_loader.dart';
class DataLoaderUI<T> extends StatefulWidget {
final ValueNotifier<DataLoader<T>> valueNotifier;
final Widget noneStatusUI;
final Widget hasErrorUI;
final Widget loadingUI;
final Widget child;
final Future<T> future;
const DataLoaderUI(
{Key? key,
required this.valueNotifier,
this.noneStatusUI = const Text('Data initialization has not started'),
this.hasErrorUI = const Center(child: Text('Unable to fetch data')),
this.loadingUI = const Center(
child: CircularProgressIndicator(),
),
required this.child,
required this.future})
: super(key: key);
#override
State<DataLoaderUI> createState() => _DataLoaderUIState();
}
class _DataLoaderUIState extends State<DataLoaderUI> {
Future startLoading() async {
widget.valueNotifier.value.status = Status.loading;
widget.valueNotifier.notifyListeners();
try {
var data = await widget.future;
widget.valueNotifier.value.data = data;
widget.valueNotifier.value.status = Status.loaded;
widget.valueNotifier.notifyListeners();
} catch (e) {
log('future error', error: e.toString());
widget.valueNotifier.value.error = e;
widget.valueNotifier.value.status = Status.hasError;
widget.valueNotifier.notifyListeners();
}
}
#override
void initState() {
super.initState();
log('init state launched');
if (!widget.valueNotifier.value.hasData) {
log('reloading or first loading');
startLoading();
}
}
//AsyncSnapshot asyncSnapshot;
#override
Widget build(BuildContext context) {
return ValueListenableBuilder<DataLoader>(
valueListenable: widget.valueNotifier,
builder: (context, dataLoader, ui) {
if (dataLoader.status == Status.none) {
return widget.noneStatusUI;
} else if (dataLoader.status == Status.hasError) {
return widget.hasErrorUI;
} else if (dataLoader.status == Status.loading) {
return widget.loadingUI;
} else {
return widget.child;
}
});
}
}
which is also simple yet very effective. since even if the initState function is relaunched if the data is already fetched the Future will not relaunch.
I am using the class like this:
class TabOne extends StatefulWidget {
static Tab tab = const Tab(
icon: Icon(Icons.upload),
);
const TabOne({Key? key}) : super(key: key);
#override
State<TabOne> createState() => _TabOneState();
}
class _TabOneState extends State<TabOne> {
#override
Widget build(BuildContext context) {
return DataLoaderUI<User>(
valueNotifier: UserData.userData,
future: UserData.loadUserData(),
child: Text(UserData.userData.value.data!.name??'No name'));
}
}
The error is in this line:
Text(UserData.userData.value.data!.name??'No name'));
Null check operator used on a null value
Since I am passing the Text widget as an argument with the data inside it. Flutter is trying to pass it but not able to since there is no data yet so its accessing null values. I tried with a normal string and it works perfectly. I looked at the FutureBuilder widget and they use a kind of builder and also the ValueLisnableBuilder has a builder as an arguement. The problem is that I am not capable of creating something like it for my custom solution. How can I just pass the child that I want without having such an error and without moving the ValueLisnable widget into my direct UI widget?
I have found the solution.
Modify the DataLoaderUI class to this:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:testing/utils/dataLoader/data_loader.dart';
class DataLoaderUI<T> extends StatefulWidget {
final ValueNotifier<DataLoader<T>> valueNotifier;
final Widget noneStatusUI;
final Widget hasErrorUI;
final Widget loadingUI;
final Widget Function(T? snapshotData) child;
final Future<T> future;
const DataLoaderUI(
{Key? key,
required this.valueNotifier,
this.noneStatusUI = const Text('Data initialization has not started'),
this.hasErrorUI = const Center(child: Text('Unable to fetch data')),
this.loadingUI = const Center(
child: CircularProgressIndicator(),
),
required this.child,
required this.future})
: super(key: key);
#override
State<DataLoaderUI<T>> createState() => _DataLoaderUIState<T>();
}
class _DataLoaderUIState<T> extends State<DataLoaderUI<T>> {
Future startLoading() async {
widget.valueNotifier.value.status = Status.loading;
widget.valueNotifier.notifyListeners();
try {
var data = await widget.future;
widget.valueNotifier.value.data = data;
widget.valueNotifier.value.status = Status.loaded;
widget.valueNotifier.notifyListeners();
} catch (e) {
log('future error', error: e.toString());
widget.valueNotifier.value.error = e;
widget.valueNotifier.value.status = Status.hasError;
widget.valueNotifier.notifyListeners();
}
}
#override
void initState() {
super.initState();
log('init state launched');
if (!widget.valueNotifier.value.hasData) {
log('reloading or first loading');
startLoading();
}
}
//AsyncSnapshot asyncSnapshot;
#override
Widget build(BuildContext context) {
return ValueListenableBuilder<DataLoader<T>>(
valueListenable: widget.valueNotifier,
builder: (context, dataLoader, ui) {
if (dataLoader.status == Status.none) {
return widget.noneStatusUI;
} else if (dataLoader.status == Status.hasError) {
return widget.hasErrorUI;
} else if (dataLoader.status == Status.loading) {
return widget.loadingUI;
} else {
return widget.child(dataLoader.data);
}
});
}
}
and use it like this:
DataLoaderUI<User>(
valueNotifier: UserData.userData,
future: UserData.loadUserData(),
child: (user) {
return Text(user!.name ?? 'kk');
});
Take a look at my version of the same sort of state management approach here: https://github.com/lukehutch/flutter_reactive_widget

Flutter - cubit: ProviderNotFoundException

Im am trying to get userData by id to show userProfile. I create a cubitProfile for this reason but when I go to the profile page the app ProviderNotFoundException(T, context.widget.runtimeType) apears. Can u help me with this error?
Here is my code:
profile
class ProfileScreen extends StatelessWidget {
final String id;
const ProfileScreen({Key? key, required this.id}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocBuilder<ProfileCubit, ProfileStates>(builder: (context, state) {
var cubit = ProfileCubit.get(context);
return Scaffold(
...
profileCubit
class ProfileCubit extends Cubit<ProfileStates> {
ProfileCubit() : super(ProfileInitState());
static ProfileCubit get(context) => BlocProvider.of(context);
late UserData userData;
void getUserDataById(String id) {
emit(ProfileGetUserLoadingState());
FirebaseFirestore.instance.collection('users').doc(id).get().then((value) {
userData = UserData.fromJson(jsonDecode(jsonEncode(value.data())));
emit(ProfileGetUserSuccessState());
}).catchError((error) {
print(error);
emit(ProfileGetUserErrorState());
});
}
bool isSameUser(String uid) {
if (FirebaseAuth.instance.currentUser!.uid != uid) {
return false;
} else {
return true;
}
}
}

SharedPreference lost data on app Killed/Close Flutter

I am saving modal object converted into String to SharedPreference and Killing the app. But when I come back to app SharedPreference has lost the saved data. I am new to flutter. Please help. I want to save my data and kill the app and again retrieve while coming back.
Here is my code
class HomeScreen extends StatefulWidget {
HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
List<User> selectedUser = [];
List<User> visibleUser = [];
double screenHeight = 0.0;
static const _keyUser = 'users';
#override
initState() {
super.initState();
WidgetsBinding.instance!.addObserver(this);
getUsersFromSharedPref();
}
Future<void> getUsersFromSharedPref() async {
final pref = await SharedPreferences.getInstance();
setState((){
String savedJson = pref.getString(_keyUser) ?? '';
if(savedJson.length > 0) {
selectedUser = UserApi.getUsersFromSharedPref(savedJson);
}
});
}
Future<void> saveInSharedPref() async {
final pref = await SharedPreferences.getInstance();
String encodedData = UserApi.getStringFromobject(selectedUser);
await pref.setString(_keyUser , encodedData);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<User>>(
future: UserApi.getUserLocally(context),
builder: (context, snapshot) {
final allUsers = (selectedUser.isNotEmpty) ? selectedUser : snapshot.data;
visibleUser = (selectedUser.isNotEmpty)?(selectedUser.where((aUser) => (aUser.isDefaultUser)).toList()) : (allUser!.where((aUser) => (aUser.isDefaultUser)).toList());
.
.
.
})
);
}
#override
void dispose() {
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
final isBackground = state == AppLifecycleState.paused;
if (isBackground || (state == AppLifecycleState.inactive ||
state == AppLifecycleState.detached)) {
saveInSharedPref();
}
if(state == AppLifecycleState.resumed){
getUserFromSharedPref();
}
}
}
class UserApi {
static Future<List<User>> getUserLocally(BuildContext context) async {
final assetBundle = DefaultAssetBundle.of(context);
final data = await assetBundle.loadString('assets/data/Users.json');
final body = json.decode(data.toString()).cast<Map<String, dynamic>>();
return body.map<User>((json) => new User.fromJson(json)).toList();
}
static List<User> getUserFromSharedPref(String jsonString){
final body = json.decode(jsonString).cast<Map<String, dynamic>>();
return body.map<User>((json) => new User.fromJson(json)).toList();
}
}
I am not getting saved data after killing the app from SharedPreferences.

How to use SharedPreference Globally?

I pass the value of both userProfileID And ,userstype to Profilepage() as shown below but when i go to profile page and I try to print the value of both this variable I will get Null value, I think they Actually not passed from this _HomePageState, anyone help?
Here is Where I pass the Value of both
userProfileID as a UserID and userstype as UserTypes inside initState() below,
and both UserID and UserTypes are Obtained from SharedPrefrence
(I call GetData to obtain the value of UserID and UserTypes from SharedPreference )
class _HomePageState extends State<HomePage> {
String UserID;
String UserTypes;
List<Widget>_children;
bool isSignedIn= false;
int _CurrentIndex=0;
void initState(){
super.initState();
GetData();
_children=[
TimeLinePage(UsersIdTimeline:UserID,UsersTypeTimeline:UserTypes),
SearchPage(searchUserSID: UserID,searchUsertype:UserTypes), //search(),
UploadPage(uploadUserSID:UserID,uploadUsertype: UserTypes),
NotificationsPage(NotifyUserSID: UserID,NotifyUsertype:UserTypes),
ProfilePage(userProfileID:UserID,userstype:UserTypes),
];
if(FirebaseAuth.instance.currentUser!=null){
setState(() {
isSignedIn= true;
});
}else{
setState(() {
isSignedIn= false;
});
}
}
#override
Widget build(BuildContext context) {
if(isSignedIn){
return buildHomeScreen();
} else{
return buildSignedInScreen();
}
}
void GetData()async {
SharedPreferences preferences= await SharedPreferences.getInstance();
setState(() {
UserID=preferences.get('UserId');
UserTypes=preferences.get('UserType');
});
}
}
here is buildHomeScreen
class _HomePageState extends State<HomePage> {
// ignore: non_constant_identifier_names
String UserID;
String UserTypes;
List<Widget>_children;
List<Widget>_agentchildren;
bool isSignedIn= false;
// ignore: non_constant_identifier_names
int _CurrentIndex=0;
int _agentCurrentIndex=0;
void initState(){
super.initState();
GetData();
_children=[
TimeLinePage(UsersIdTimeline:UserID,UsersTypeTimeline:UserTypes),
SearchPage(searchUserSID: UserID,searchUsertype:UserTypes),
UploadPage(uploadUserSID:UserID,uploadUsertype:UserTypes),
NotificationsPage(NotifyUserSID: UserID,NotifyUsertype:UserTypes),
ProfilePage(userProfileID:UserID,userstype:UserTypes),
];
if(FirebaseAuth.instance.currentUser!=null){
setState(() {
isSignedIn= true;
});
}else{
setState(() {
isSignedIn= false;
});
}
}
#override
Widget build(BuildContext context) {
if(isSignedIn){
if(UserTypes=='agent'){
return buildagentScreen();
} else if(UserTypes== 'Signupuser'||
UserTypes== 'owner'||
UserTypes== 'seller'
){
return buildHomeScreen();
}else{
return buildSignedInScreen();
}
}
}
Here is My ProfilePage(), if I try to get the value of both
( String userstype; String userProfileID;) in this page
i get Null value but I alredy pass the value of them from the above _HomePageState()
class ProfilePage extends StatefulWidget {
String userstype;
String userProfileID;
ProfilePage({this.userProfileID, this.userstype});
#override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
final String CurrentOnlineUserID=curentuser?.uid;
bool loading =false;
int countPost=0;
String postOrientation="grid";
List<Post> PostList=[];
void initState(){
getAllProfilePost();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar:header(context,strTitle:"profile"),
body:ListView(
children:<Widget>[
TopView(),
]
),
);
}
Use shared preferences globally for your application.
import 'dart:async' show Future;
import 'package:shared_preferences/shared_preferences.dart';
class PreferenceUtils {
static Future<SharedPreferences> get _instance async => _prefsInstance ??= await SharedPreferences.getInstance();
static SharedPreferences _prefsInstance;
// call this method from iniState() function of mainApp().
static Future<SharedPreferences> init() async {
_prefsInstance = await _instance;
return _prefsInstance;
}
static String getString(String key, [String defValue]) {
return _prefsInstance.getString(key) ?? defValue ?? "";
}
static Future<bool> setString(String key, String value) async {
var prefs = await _instance;
return prefs?.setString(key, value) ?? Future.value(false);
}
}
Please follow this link
https://stackoverflow.com/a/61046061/8218866
When the _HomePageState is created, the initState is called, and so this line:
_children=[
[...],
ProfilePage(userProfileID:UserID,userstype:UserTypes),
];
This line is creating the object of a ProfilePage with the desired UserID's and UserTypes. This ProfilePage object will be put inside the _children list.
When you do this:
setState(() {
UserID=preferences.get('UserId');
UserTypes=preferences.get('UserType');
});
You are 1) calling the build method again, and 2) updating the value of UserID and UserTypes. You did not change the value of any itens inside the _childrens list. Or the list itself. Hence the misbehavior you noticed.
There are many ways to solve this, but the essence would be to move this list declaration inside the build method. An example:
#override
Widget build(BuildContext context) {
_children = [.....]
if(isSignedIn){
[...]
Doing this way would not be a pretty way to do it, because you are creating lots of new (and useless) objets every time the build method is called. Maybe in a small application this wouldn't be a problem, and for didactic reasons I chose to show this way in this answer.
The more correct way would be to :
Switch and instantiate inside buildHomeScreen the body object:
Scaffold buildHomeScreen(){
Widget body;
switch (_currentIndex) {
case 0:
body =
TimeLinePage(UsersIdTimeline:UserID,UsersTypeTimeline:UserTypes);
break;
case 1:
body = ...;
break;
}
return Scaffold(
...
body: body,
...
)
}
Which should give you the same result.

Data not being updated after change the placeID in flutter BLoC

I am working on one project with BLoC.I have made some classes to update the data.
Data will come once you pass the placeID.
But once you pass the PlaceID first time it will give the data and widgets updated.
But once I pass new placeID old data not being updated. It shows old data.
All Code Files:
RestaurantDetailBloc.dart
class RestaurantDetailBloc extends Bloc<RestaurantDetailEvent, RestaurantDetailState> {
static final RestaurantDetailBloc _restaurantDetailBlocSingleton = new RestaurantDetailBloc._internal();
factory RestaurantDetailBloc() {
return _restaurantDetailBlocSingleton;
}
RestaurantDetailBloc._internal();
RestaurantDetailState get initialState => new UnRestaurantDetailState();
#override
Stream<RestaurantDetailState> mapEventToState(
RestaurantDetailEvent event,
) async* {
try {
yield await event.applyAsync(currentState: currentState, bloc: this);
} catch (_, stackTrace) {
print('$_ $stackTrace');
yield currentState;
}
}
}
LoadRestaurantDetailEvent.dart
#immutable
abstract class RestaurantDetailEvent {
Future<RestaurantDetailState> applyAsync(
{RestaurantDetailState currentState, RestaurantDetailBloc bloc});
final RestaurantDetailProvider _provider = RestaurantDetailProvider();
}
class LoadRestaurantDetailEvent extends RestaurantDetailEvent {
#override
String toString() => 'LoadRestaurantDetailEvent';
String placeID;
LoadRestaurantDetailEvent({Key key,this.placeID});
#override
Future<RestaurantDetailState> applyAsync(
{RestaurantDetailState currentState, RestaurantDetailBloc bloc}) async {
try {
await Future.delayed(new Duration(seconds: 2));
var component = await _provider.getRestaurantReview(placeID);
print(component);
return new InRestaurantDetailState(component);
} catch (_, stackTrace) {
print('$_ $stackTrace');
return new ErrorRestaurantDetailState(_?.toString());
}
}
}
RestaurantDetailPage.dart
class RestaurantDetailPage extends StatelessWidget {
static const String routeName = "/restaurantDetail";
final String imageURL;
final String placeID;
const RestaurantDetailPage({Key key, this.imageURL,this.placeID}) : super(key: key);
#override
Widget build(BuildContext context) {
var _restaurantDetailBloc = new RestaurantDetailBloc();
return new RestaurantDetailScreen(restaurantDetailBloc: _restaurantDetailBloc,imageUrl: this.imageURL,placeId: this.placeID,);
}
}
RestaurantDetailProvider.dart
class RestaurantDetailProvider {
String getBaseUrl(String placeID){
final urlBase = "https://maps.googleapis.com/maps/api/place/details/json?placeid=$placeID&key=xxxxxxxxxxxxxGooglePlaceKey";
return urlBase;
}
Future<void> loadAsync(String token) async {
/// write from keystore/keychain
await Future.delayed(new Duration(seconds: 2));
}
Future<void> saveAsync(String token) async {
/// write from keystore/keychain
await Future.delayed(new Duration(seconds: 2));
}
Future<Map<String, dynamic>> getRestaurantReview(String placeId)async{
var response = await http.get(getBaseUrl(placeId));
RestaurantReviews reviews = RestaurantReviews();
if(response.statusCode == 200){
var decodedJson = jsonDecode(response.body);
print(decodedJson);
//reviews.result = decodedJson['result'];
return decodedJson;
}
else{
}
}
}
InRestaurantDetailState.dart
#immutable
abstract class RestaurantDetailState extends Equatable {
RestaurantDetailState([Iterable props]) : super(props);
/// Copy object for use in action
RestaurantDetailState getStateCopy();
}
/// UnInitialized
class UnRestaurantDetailState extends RestaurantDetailState {
#override
String toString() => 'UnRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return UnRestaurantDetailState();
}
}
class InRestaurantDetailState extends RestaurantDetailState {
final resReview;
InRestaurantDetailState(this.resReview);
#override
String toString() => 'InRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return InRestaurantDetailState(resReview);
}
}
class ErrorRestaurantDetailState extends RestaurantDetailState {
final String errorMessage;
ErrorRestaurantDetailState(this.errorMessage);
#override
String toString() => 'ErrorRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return ErrorRestaurantDetailState(this.errorMessage);
}
}
RestaurantDetailScreenState.dart
class RestaurantDetailScreen extends StatefulWidget {
const RestaurantDetailScreen({
Key key,
#required RestaurantDetailBloc restaurantDetailBloc,
this.imageUrl, this.placeId,
}) : _restaurantDetailBloc = restaurantDetailBloc,
super(key: key);
final RestaurantDetailBloc _restaurantDetailBloc;
final String imageUrl;
final String placeId;
#override
RestaurantDetailScreenState createState() {
return new RestaurantDetailScreenState(_restaurantDetailBloc, imageUrl,placeId);
}
}
class RestaurantDetailScreenState extends State<RestaurantDetailScreen> {
final RestaurantDetailBloc _restaurantDetailBloc;
final String imageUrl;
final String placeId;
RestaurantDetailScreenState(this._restaurantDetailBloc, this.imageUrl,this.placeId);
#override
void initState() {
super.initState();
this._restaurantDetailBloc.dispatch(LoadRestaurantDetailEvent(placeID:placeId));
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
return BlocBuilder<RestaurantDetailBloc, RestaurantDetailState>(
bloc: widget._restaurantDetailBloc,
builder: (
BuildContext context,
var currentState,
) {
if (currentState is UnRestaurantDetailState) {
return MaterialApp(
home: new Scaffold(
body: new Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
),
));
}
if (currentState is ErrorRestaurantDetailState) {
return new Container(
child: new Center(
child: new Text(currentState.errorMessage ?? 'Error'),
));
}
if (currentState is InRestaurantDetailState) {
var resList = currentState.resReview;
print(resList);
return MaterialApp(
home: new Scaffold(
)
);
}
Please help me guys.I have spent whole day.
Thank you in advance.
You need to pass the data to the parent class for comparison. That's why we are using equatable. Do these changes and it should work. Let me know if it doesn’t.
class InRestaurantDetailState extends RestaurantDetailState {
final resReview;
//You need to change this line to
InRestaurantDetailState(this.resReview):super([resReview]);
#override
String toString() => 'InRestaurantDetailState';
#override
RestaurantDetailState getStateCopy() {
return InRestaurantDetailState(resReview);
}
}