I am trying to develop login checker. The following code should redirect to HomeScreen when user is loggedin and to LoginPage in User is not loggedin. But it only gets redirect to LoginScreen() not to HomeScreen() even though it's already logged in.
User Model:
class User {
User({
required this.id,
required this.name,
required this.email,
required this.cart,
});
String id;
String name;
String email;
List cart;
}
UserController:
class UserController extends GetxController {
RxString id = ''.obs;
RxBool isLoggedIn = false.obs;
RxString name = ''.obs;
RxString email = ''.obs;
RxString image = ''.obs;
RxList cart = [].obs;
final NetworkHandler _handler = NetworkHandler();
#override
void onInit() {
super.onInit();
getUserDetails();
}
getUserDetails() {
User _user = _handler.userDetails();
id.value = _user.id;
if (id.value != '') {
isLoggedIn.value = true;
}
name.value = _user.name;
}
}
Checker Screen
class StateCheck extends StatelessWidget {
var controller = Get.put(UserController());
StateCheck({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Obx(
() => controller.isLoggedIn.value
? const HomeScreen()
: const LoginScreen(),
);
}
}
First you have to set login value in SharedPreferences.
when login success
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("isLogin", true);
log out
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("isLogin", false);
You can Check login state || check this in splash screen for best practice (inside init method)
if(prefs.getBool('isLogin')==null||prefs.getBool('isLogin')==false){
// login screen
}else{
// home screen
}
Related
After i have created the sign in and signup in flutter and i have connect it to firebase, i added a textfield for the name of the user. So if the user register his name also will be stored, then this data is saved into firebase with the id of the user. The problem is when i try to fetch this data my these method it gives me null ,
This is the way how i am fetching the data of the user :
class WelcomePage extends StatefulWidget {
String email;
WelcomePage ({Key? key, required this.email}) : super(key: key);
#override
State<WelcomePage> createState() => _WelcomePageState();
}
class _WelcomePageState extends State<WelcomePage> {
ScrollController? _scrollcontroller;
final FirebaseAuth _auth =FirebaseAuth.instance;
String? _name ;
String? _uid;
#override
void initState() {
super.initState();
_scrollcontroller = ScrollController();
_scrollcontroller?.addListener(() {
setState(() {});
});
getData();
}
void getData() async{
User? user = _auth.currentUser;
_uid = user!.uid;
final DocumentSnapshot userDoc =
await FirebaseFirestore.instance.collection('users').doc(user.uid).get();
_name = userDoc.get('name');
}
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';
Am trying to achieve app that if person logged in the response of app is sent to another screen. here it is asking to add the same details in splash screen, am using shared preferences to see the user is logged in or not. how can we fix this issue.
splash.dart
#override
void initState() {
super.initState();
// navigate();
getValidationData().whenComplete(() async {
Future.delayed(const Duration(seconds: 6), () {
PageNavigator(ctx: context).nextPageOnly(
page: finalEmail == null ? const LoginPage() : const HomeScreen(// what to do here));
});
});
}
login.dart
///Save users data and then navigate to homepage
final int userId = res['userId'];
final String token = res['token'];
final bool recharge = res['recharge'];
final String name = res['name'];
PageNavigator(ctx: context).nextPageOnly(
page: HomeScreen(
userId: userId,
token: token,
recharge: recharge,
name: name,
));
home.dart
class HomeScreen extends StatefulWidget {
final int userId;
final String token;
final bool recharge;
final String name;
const HomeScreen({
Key? key,
required this.userId,
required this.token,
required this.recharge,
required this.name,
}) : super(key: key);
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.
I have 3 screens, login, homepage and chat. In chat I want to use user, but for some reasons I am getting an error.
Error in HomePage class while trying to pass user to the Chat: 'Undefined name 'user''.
Here samples of code:
class Login extends StatefulWidget {
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
String email;
String password;
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> login(String _email, String _password) async {
FirebaseUser user = (await _firebaseAuth.signInWithEmailAndPassword(
email: _email, password: _password))
.user;
() =>
Navigator.push(context, MaterialPageRoute(builder: (context) => Bar(user: user)));
}
...
Why is it not defined? I want to pass user from Login(), through Homepage() to the Chat().
Thank you in advance
EDIT:
I noticed it is not defined only in List, but besides it works properly.
How can I pass it to the list?
class HomePage extends StatefulWidget {
final FirebaseUser user;
const HomePage({Key key, this.user}) : super(key:key);
#override
_BarState createState() => _BarState();
}
class _BarState extends State<HomePage> {
void test() {
() =>
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) =>
Chat(user: widget.user))); < ---- WORKING
}
int tabIndex = 0;
List<Widget> widgetOptions = [
Match(),
Chat(user: widget.user), < --- NOT WORKING
AddBook(),
Profile(),
];
Here you want to access user object in other screen, instead of passing it in cconstructor, create a singleton class, Like this
class AuthUser {
static var authUserId;
static var email;
static var userName;
static var role;
static var companyId;
}
During login Set values like this, please check here print(user); and set value respectively
Future<String> login(String _email, String _password) async {
FirebaseUser user = (await _firebaseAuth.signInWithEmailAndPassword(
email: _email, password: _password))
.user;
() =>
AuthUser.email = user.email,
AuthUser.email = user.userName,
..........
));
}
Access data in other screens like, AuthUser.email, AuthUser.userName.....
Use Chat(user: widget.user) instead.
when you are using a stateful widgets and what to get properties from constructor you need to do it like this:
widget.varNameInConstructor
most of the time it's not needed but if you want to assign that to you own new variable in state you can do it at initState.