Reputation: 2842
I'm new to flutter and provider. I only want to change from login to home widget after the user logs in. I have a wrapper widget that listen to the user model if it was changed and will automatically show authentication widget or the home widget. The code below does not notify the wrapper that the user is not null after i logged in. I don't know it this is the correct way of using it but i hope you can help me.
//main.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<User>.value(
value: User(),
child: MaterialApp(),
home: Wrapper(),
),
);
}
}
//wrapper.dart
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
//return either home or authenticate widget
print(user);
if (user == null) {
return Authenticate();
} else {
return Home();
}
}
}
//authenticate.dart
class Authenticate extends StatefulWidget {
@override
_AuthenticateState createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
@override
Widget build(BuildContext context) {
return Container(
child: Signin(),
);
}
}
class Signin extends StatefulWidget {
@override
_SigninState createState() => _SigninState();
}
class _SigninState extends State<Signin> {
final AuthService _auth = AuthService();
@override
Widget build(BuildContext context) {
return Container(
child: MaterialButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
dynamic result = await _auth.login(username, password);
}
},
)
)
//auth.dart
class AuthService {
static const endpoint = 'http://192.168.254.100:8000';
var client = new http.Client();
Future login(String user, String password) async {
try {
var response = await client.get('$endpoint/rest_login/?username=test&password=test');
return User.fromJson(json.decode(response.body));
} catch (e) {
return null;
}
}
}
//user.dart
class User with ChangeNotifier {
int id;
String name;
String username;
String email;
String session;
User({this.id, this.name, this.username, this.email, this.session});
User.initial()
: id = 0,
name = '',
username = '',
email = '',
session = '';
User.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
username = json['username'];
email = json['email'];
session = json['session'];
notifyListeners();
}
}
Upvotes: 1
Views: 1634
Reputation: 15073
User.fromJson
is an constructor. Don't call notifyListeners()
there.
You have to specify Consumer
widgets for the model, So that it can get rebuild when the model calls notifyListeners()
.
This may help,
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<UserModel>.value(
value: UserModel(),
child: MaterialApp(
home: Wrapper(),
),
);
}
}
//wrapper.dart
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
//return either home or authenticate widget
return Consumer<UserModel>(
builder: (context, userModel, child) {
if (userModel.user == null) {
return Authenticate();
} else {
return Home();
}
},
);
}
}
//authenticate.dart
class Authenticate extends StatefulWidget {
@override
_AuthenticateState createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
@override
Widget build(BuildContext context) {
return Material(
child: SignIn(),
);
}
}
class SignIn extends StatefulWidget {
@override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
final AuthService _auth = AuthService();
@override
Widget build(BuildContext context) {
return Container(
child: MaterialButton(
child: Text("Login"),
onPressed: () async {
final user = await _auth.login("Name", "Password");
Provider.of<UserModel>(context, listen: false).user = user;
},
),
);
}
}
//auth.dart
class AuthService {
static const endpoint = 'http://192.168.254.100:8000';
var client = new http.Client();
Future<User> login(String user, String password) async {
// Use your logic and return User or null
return User(name: "Name");
}
}
//user.dart
class User {
int id;
String name;
String username;
String email;
String session;
User({this.id, this.name, this.username, this.email, this.session});
User.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
username = json['username'];
email = json['email'];
session = json['session'];
}
}
//home.dart
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text("Home Page"),
),
);
}
}
//user_model.dart
class UserModel extends ChangeNotifier {
User _user;
User get user => _user;
set user(User value) {
_user = value;
//here the model value changes. you can call 'notifyListeners' to notify all the 'Consumer<UserModel>'
notifyListeners();
}
}
Upvotes: 1
Reputation: 451
The way to use ChangeNotifierProvider is:
Widget create(BuildContext context) {
return ChangeNotifierProvider<ModelClass>(
builder: (context) => ModelClass(auth: auth),
child: Consumer<ModelClass>(
builder: (context, model, _) => View(model: model),
),
);
}
Going by the above logic:
return ChangeNotifierProvider<User>(
builder: (context) => User(auth: auth),
child: Consumer<User>(
builder: (context, user, _) =>
YourView(user: user),
),
)
You need to make changes to your MyApp widget.
Please let me know if it helps. Thanks.
Upvotes: 0