how to access to variable from StatefulWidget to State class flutter - flutter

I try to pass data from page one to page two data is pass OK but I have one problem now.
this is my code:
class SecondScreen extends StatefulWidget {
final int itemHolder ;
SecondScreen({Key key, #required this.itemHolder}) : super(key: key);
#override
State<StatefulWidget> createState() {
return new mainState();
}
}
class mainState extends State <SecondScreen> {
bool value = false ;
MyPreferences _myPreferences = MyPreferences();
#override
void initState() {
// TODO: implement initState
super.initState();
initial();
}
void initial() async {
setState(() {
});
}
final String apiURL = 'http://xxxxxxxxx/getFlowersList.php';
Future<List<Flowerdata>> fetchFlowers() async {
var response = await http.get(apiURL);
if (response.statusCode == 200) {
final items = json.decode(response.body).cast<Map<String, dynamic>>();
List<Flowerdata> listOfFruits = items.map<Flowerdata>((json) {
return Flowerdata.fromJson(json);
}).toList();
return listOfFruits;
}
else {
throw Exception('Failed to load data from Server.');
}
}
I try to use var (itemHolder ) in the link like that:
final String apiURL = 'http://xxxxxxx/getFlowersList.php?id=' +itemHolder;
but I get error:
Undefined name 'itemHolder'. Try correcting the name to one that is defined, or defining the name.
I can access to itemHolder. So how can I access to it?

try this:
...
String apiURL;
#override
void initState() {
super.initState();
apiURL = 'http://xxxxxxx/getFlowersList.php?id=' +widget.itemHolder.toString();
}
...

To use the variables declared in the SecondScreen you have to access it with the prefix 'widget' and the dot operator, not directly. Here is the code:
final String apiURL = 'http://xxxxxxx/getFlowersList.php?id=' + widget.itemHolder;
And when you make the variable final, you have to initialize it while declaration or through constructor else delete keyword final:

Related

LateError (LateInitializationError: Field 'gP1' has not been initialized.)

Can someone explain to me where I am wrong? I am programming this application and, working with sqflite, I have had this kind of problem several times when I use the readPlayer() function.
class matchesRow extends StatefulWidget {
final List matches;
final List results;
final int index;
matchesRow({
Key? key,
required this.index,
required this.matches,
required this.results,
}) : super(key: key);
#override
State<matchesRow> createState() => _matchesRowState();
}
class _matchesRowState extends State<matchesRow> {
late Player gP1;
late Player gP2;
bool ripescato = false;
PlayersDatabase pb = PlayersDatabase.instance;
#override
void initState() {
super.initState();
getPlayers();
}
#override
void dispose() {
PlayersDatabase.instance.close();
super.dispose();
}
Future getPlayers() async {
List<dynamic> duel = widget.matches[widget.index];
gP1 = await pb.readPlayer(duel[0]);
print(gP1);
gP2 = await pb.readPlayer(duel[0]);
if (duel[1] == "R") {
ripescato = true;
} else {
gP2 = await pb.readPlayer(duel[1]);
}
}
#override
Container build(BuildContext context) {
var icon = Icons.code_sharp;
return Container(child: Text(gP1.name));
}}
This is the function ReadPlayer()
Future<Player> readPlayer(int id) async {
final db = await instance.database;
final maps = await db.query(
tablePlayers,
columns: PlayerFields.values,
where: '${PlayerFields.id} = ?',
whereArgs: [id],
);
if (maps.isNotEmpty) {
return Player.fromJson(maps.first);
} else {
throw Exception('ID $id not found');
}
I don't understand why even if I declare the value of gP1 and gP2 in getPlayers() the error still pop up.
gP1 and gP2 getting from future method. It will take some time to fetch data from future method getPlayers. Use FutureBuilder or make it nullable
For nullable case it will be
Player? gP1;
Player? gP2;
#override
void initState() {
super.initState();
getPlayers().then((value) {
//update Ui after getting data
setState(() {});
});
}
And use case with default value on null case
Text(gP1?.name??"didnt get yet")

Problems with shared preference-flutter

I wanna ask how to save state from textfield? cause i can't saving this state, after hot restart my value always reset, i just want to save state after hot restart, can i know my problem where it's wrong?
it's my code:
class HomePage extends StatefulWidget {
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextEditingController nameController = TextEditingController();
var nama = 'nama';
void setPref() async {
var prefs = await SharedPreferences.getInstance();
prefs.setString(nama, nameController.text);
}
void load() async {
var prefs = await SharedPreferences.getInstance();
setState(() {
nama = prefs.getString(nameController.text) ?? '';
nameController.text = nama;
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
load();
}
#override
Widget build(BuildContext context) {
.....
}
}
There is a problem in your code:
In shared Prefrences you have to use key to store and get value.
But you are using it in wrong way:
Here is correct code:
void load() async {
var prefs = await SharedPreferences.getInstance();
String value = '';
setState(() {
value= prefs.getString(nama) ?? '';
nameController.text = value;
});
}
The nama is a key name and you are also using it to receive value. And the key you are using is nameController.text is also wrong.
Bonus
The convection of writing keys in Flutter is Following:
String nameKey = 'NAMEKEY';

Assigning the sharedPreference value to a variable within the build

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!);
}
}

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.

get data from constructor and pass it to variable

I want to get the data from the constructor and passes it to a variable.
I dont want it to be listed...
Class:
class ListaProjetos extends StatefulWidget {
ListaProjetos({Key key, this.title, this.jsonData}) : super(key: key);
static const String routeName = "/ListaProjetos";
final String title;
final List jsonData;
#override
_ListaProjetosState createState() => _ListaProjetosState();
}
I want to:
class _ListaProjetosState extends State<ListaProjetos> {
var message = widget.jsonData;
print(message);
//HERE I WANT TO PRINT ALL JSON DATA
}
Inside the class you need create a method and place the variables initialization, for example:
#override
void initState() {
var message = widget.jsonData;
print(message);
}
Or you can declare the var outside of the method to use it in others methods.
var message;
#override
void initState() {
message = widget.jsonData;
print(message);
}