Flutter : Call value from second function class - flutter

I have Auth class which has sgin in function and inside of this function value for example user value , so how to get this value from Auth class to Home class ?
Here Auth class and Home Class :
class Auth {
void signIn(){
String user = "I LOVE PROGRAMMING";
}
}
class Home {
return Text("$user") //Iwant user value from clas AUTH
}

You would want to have the signIn function return the user.
class Auth {
String signIn() {
String user = "I LOVE PROGRAMMING";
return user;
}
}
Then you can call that from another class:
class Home {
Widget someFunction() {
final auth = Auth(); // create a new instance of Auth
final user = auth.signIn(); // call the function and put the return value in a `user` variable
return Text(user); // use the `user` String in the Text widget
}
}
I would advice you to have a look at the Dart language tour and learn about these things step by step. These are the basics you will need to get anything done. Good luck!

You should be implement below way
class Auth {
static String _user;
void signIn() {
_user = "dfsdfgdfgfdgdfgfdgfdgfdgfd";
}
static String getUser() => _user;
}
class Home {
return Text(Auth.getUser())
}

Firstly, you need to create a global variable for the String user that you have set in the Auth class and create a getter for it. You also would need to use some type of state management to simulate the value changes. In this case I'll use the provider package.
class Auth extends ChangeNotifier{
String _user = '';
void signIn() {
_user = 'SomethinInteresting';
}
String get userName => _user;
}
Whenever the signIn() function is being called from other component, the value for the user would be set. And finally if you want to access the value from other component you can use the getter to set the value in the Text component.
class Home {
final _auth = Provider.of<Auth>(context);
#override
Widget build(BuildContext context) {
return text(_auth.userName);
}
}
This would also facilitate dyanmic changes to the fields in the Auth class.

For accessing the value from the "Auth" class you first need to make the method type String and return the value when the method is called. In the Home class there must be main method as it is from where the execution of the program starts. Now, create an object of class "Auth" and call the method using the same object. You'll get the user value.
class Auth {
String signIn(){
String user = "dfsdfgdfgfdgdfgfdgfdgfdgfd";
return user;
}
}
class Home {
public static void main(String args[]){
Auth ob=new Auth();
System.out.println(ob.signIn());//I want user value from clas AUTH
}
}

Related

Flutter Provider: Should I create a new Provider for every class?

Lets say I have multiple settings a user can set. Should I have one Provider which manages all settings like so:
class Settings with ChangeNotifier {
SettingsA _settingsA;
SettingsB _settingsB;
List<String> _settingsC;
SettingsA get settingsA => _settingsA;
SettingsB get settingsB => _settingsB;
List<String> get settingsC => _settingsC;
// Setters
void updateA(SettingsA settingsA) {
_settingsA = settingsA;
notifyListeners();
}
void updateB(SettingsB settingsB) {
_settingsB = settingsB;
notifyListeners();
}
void addToC(String setting) {
_settingsC.add(setting);
notifyListeners();
}
}
Or should I rather make a Provider for every object like so:
class SettingsAProvider with ChangeNotifier {
SettingsA _settingsA;
SettingsA get settingsA => _settingsA;
// Setters
void update(SettingsA settingsA) {
_settingsA = settingsA;
notifyListeners();
}
}
What is the best practise of using ChangeNotifierProviders?
In my opinion, you should use SettingAProvider,SettingBProvider,...
If you use Settings Class...
When you call updateA, it will notify all value _settingA,_settingB,_settingC,... even if unecessary.

Combining Riverpod Providers Bidirectionally

How can we access a method from the being wrapped riverpod provider?
ContentProvider can access user value from UserProvider by using "watch". There is no problem for this direction. On the other hand, UserProvider also needs access to the methods of ContentProvider. So bidirectional communication is required.
For this case, I need to call deleteContents method from UserProvider.
I don't prefer to merge them to keep logic safe.
class ContentProviderNotifier extends ChangeNotifier {
final User? currentUser;
ContentProviderNotifier({required this.currentUser});
addContent(Content content) {
content.user = currentUser?.name;
...
}
deleteContents() {
...
}
}
final contentProvider = ChangeNotifierProvider<ContentProviderNotifier>(
(ref) {
final user = ref.watch(userProvider).currentUser;
return ContentProviderNotifier(currentUser: user);
},
);
class UserProviderNotifier extends ChangeNotifier {
UserProviderNotifier();
User? currentUser;
deleteUsers(){
// here to call a method from contentProvider
deleteContents();
}
}
final userProvider = ChangeNotifierProvider<UserProviderNotifier>(
(ref) {
return UserProviderNotifier();
},
);
If I try to feed UserProvider with ContentProvider like this
final userProvider = ChangeNotifierProvider<UserProviderNotifier>(
(ref) {
final content = ref.watch(contentProvider); // <----
return UserProviderNotifier(content);
},
);
But I know, It won't make sense.
The type of 'userProvider' can't be inferred because it depends on itself through the cycle: contentProvider, userProvider.
Try adding an explicit type to one or more of the variables in the cycle in order to break the cycle.darttop_level_cycle
You can create UserProviderNotifier so it takes ref as an input, like this:
class UserProviderNotifier extends ChangeNotifier {
UserProviderNotifier(this.ref);
final Ref ref;
deleteUsers() {
// here to call a method from contentProvider
ref.watch(contentProvider.notifier).deleteContents();
}
}
final userProvider = ChangeNotifierProvider<UserProviderNotifier>(
(ref) {
return UserProviderNotifier(ref);
},
);
This section of the Riverpod docs mentions this is a common use-case.

Can you access riverpod from a flutter action?

I am wanting to create an action so that the user can either click a button or hit a key to perform an update on a StateNotifier's state (and then update the ui). But I realize after I figure out how to get Actionsworking that I don't have access to WidgetRef or ref so that I can update the provider.
Is it possible to use actions with Riverpod? Would I need to send ref to the action or is that too much lifting and against the point?
class RemoveFileIntent extends Intent {
const RemoveFileIntent();
}
class RemoveFileAction extends Action<RemoveFileIntent> {
RemoveFileAction();
#override
Object? invoke(covariant RemoveFileIntent intent) {
// update riverpod StateNotifier's state?
return null;
}
}
There are two options. You could create your action in a provider, then pass the provider's Ref to the constructor of your object:
final removeFileActionProvider = Provider(RemoveFileAction.new);
class RemoveFileAction extends Action<RemoveFileIntent> {
RemoveFileAction(this.ref);
final Ref ref;
#override
Object? invoke(covariant RemoveFileIntent intent) {
ref.read(provider).doSomething(intent);
return null;
}
}
Or create your action in a ConsumerWidget/Consumer/ConsumerStatefulWiget, and pass WidgetRef instead of Ref

Flutter - Retrieve MobX #action return value in screen load without click

I have MobX #action which successfully return a value. Wondering how to retrieve the value in initial screen load without click or tap anything.
abstract class _ProfileMobx with Store {
#observable
User user;
#observable
String name = '';
#action
Future getClientName() async {
SharedPreferences pref = await SharedPreferences.getInstance();
User user = User.fromJson(json.decode(pref.getString('userPref')));
name = user.name; //successfully return an username from this action
}
}
I hope I can get the username value and inserted automatically to text widget.
final ProfileMobx profileMobx = ProfileMobx();
class ProfileView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text(profileMobx.name)
],
),
);
}
}
Thanks !!!
Have you tried #computed?
Basically computed values are values that can be derived (computed) from the existing state or other observable/computed values.
I am not 100% sure about Dart, but in Javascript/Typescript it would look something like that:
class Profile {
#observable
user :User
#computed get name() {
return this.user ? this.user.name : '';
}
#action
getUser = async () => {
// .. your code to get user
this.user = await getUser();
// Don't need this line, just set the user, computed will be automatically recalculated
// name = user.name;
}
}
More info about computed here: https://mobx.js.org/refguide/computed-decorator.html
Or here, if you use Dart, I guess: https://pub.dev/packages/mobx#computed-observables

Making Private Route in Flutter

How can I make a wrapper over my private routes, which navigate to screen only when user is authorized, otherwise redirect to login and get back to the original screen after login.
How can make this in a generalized way, so that I just reuse it on my other Private future screens?
If you are using routes parameter in your MaterialApp, you can replace it with following implementation
import 'dart:collection';
import 'package:flutter/widgets.dart';
class ConditionalRouter extends MapMixin<String, WidgetBuilder> {
final Map<String, WidgetBuilder> public;
final Map<String, WidgetBuilder> private;
ConditionalRouter({this.public, this.private});
#override
WidgetBuilder operator [](Object key) {
if (public.containsKey(key))
return public[key];
if (private.containsKey(key)) {
if (MyAuth.isUserLoggedIn)
return private[key];
// Adding next page parameter to your Login page
// will allow you to go back to page, that user were going to
return (context) => LoginPage(nextPage: key);
}
return null;
}
#override
void operator []=(key, value) {}
#override
void clear() {}
#override
Iterable<String> get keys {
final set = Set<String>();
set.addAll(public.keys);
set.addAll(private.keys);
return set;
}
#override
WidgetBuilder remove(Object key) {
return public[key] ?? private[key];
}
}
And use it like that:
MaterialApp(
// ...
routes: ConditionalRouter(
public: {
'/start_page': (context) => StartPage()
},
private: {
'/user_profile': (context) => UserProfilePage()
}
)
)
Use StreamBuilder widget and provide it a Stream of access token/uid if there is no data then return login screen and when user is authenticated then put access token into the stream that will rebuild the StreamBuilder which return the page when user is authenticated.
Use bloc pattern or bloc library for better state management.
Hope this will help you.
Generalised idea, you could make the controller a Static variable
class LoginController{
final Function onContactingServerDone;
LoginController({this.onContactingServerDone,});
bool loggedIn;
login()async {
//contact server,get token or verify token etc
onContactingServerDone();
}
}
and in your screen
LoginController _loginController;
initState(){
_loginController = LoginController(onContactingServerDone: (){
if(_loginController.loggedIn){
Navigator.of(context).pushNamed('privateRoute');
} else {
Navigator.of(context).pushNamed('login');
}
},);
_loginController.login();
}
Widget build(context){
return CircularProgressIndicator();
}