Add value from Sharedpreferences in variable (stateful widget) - flutter

I saved the data using SharedPreferences, when my app is starting i try check type of user "client" or "company" after that wil be shown screen.
Future<void> setTypeClient() async {
final _storage = SharedPreferences.getInstance();
final storage = await _storage;
storage.setString('type_user_db', 'client');
}
My app is starting
I have variable
var typeUser = ' ' ; and use it when I determine which screen to display
Аfter I get the data from SharedPreferences, I need to put value in this variable
But i have an error, cause variable remains empty
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../views/home_view.dart';
import '../views/auth/client_auth_view.dart';
import '../views/auth/company_auth_view.dart';
import '../views/auth/company_reg_view.dart';
import '../views/client/client_view.dart';
import '../views/company/company_view.dart';
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MyAppBody();
}
}
class MyAppBody extends StatefulWidget {
const MyAppBody({Key? key}) : super(key: key);
#override
State<MyAppBody> createState() => _MyAppBodyState();
}
class _MyAppBodyState extends State<MyAppBody> {
Future<void> getTypeUser() async {
final storage = await SharedPreferences.getInstance();
final type = storage.getString('type_user_db');
setState(() {
typeUser = type!;
});
}
var typeUser = '';
Map<String, Widget> screenByUser = {
'client': const ClientView(),
'company': const CompanyView(),
};
bool isLogOut = true;
#override
void initState() {
if (FirebaseAuth.instance.currentUser != null) {
getTypeUser();
setState(() {
isLogOut = false;
});
super.initState();
} else {
return;
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Well Plus',
debugShowCheckedModeBanner: false,
routes: {
'/main': (context) => const HomeView(),
'/auth_client': (context) => const AuthClientView(),
'/auth_company': (context) => const AuthCompanyView(),
'/reg_company': (context) => const RegCompanyView(),
'/client': (context) => const ClientView(),
'/company': (context) => const CompanyView(),
},
home: isLogOut ? const HomeView() : screenByUser[typeUser],
);
}
}
update
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../views/home_view.dart';
import '../views/auth/client_auth_view.dart';
import '../views/auth/company_auth_view.dart';
import '../views/auth/company_reg_view.dart';
import '../views/client/client_view.dart';
import '../views/company/company_view.dart';
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MyAppBody();
}
}
class MyAppBody extends StatefulWidget {
const MyAppBody({Key? key}) : super(key: key);
#override
State<MyAppBody> createState() => _MyAppBodyState();
}
class _MyAppBodyState extends State<MyAppBody> {
Future<void> getTypeUser() async {
final storage = await SharedPreferences.getInstance();
final type = storage.getString('type_user_db');
setState(() {
typeUser = type!;
});
}
var typeUser = '';
Map<String, Widget> screenByUser = {
'client': const ClientView(),
'company': const CompanyView(),
};
bool get isLogOut => typeUser.isEmpty;
#override
void initState() {
if (FirebaseAuth.instance.currentUser == null) {
getTypeUser();
setState(() {
isLogOut = false;
});
super.initState();
} else {
return;
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Well Plus',
debugShowCheckedModeBanner: false,
routes: {
'/main': (context) => const HomeView(),
'/auth_client': (context) => const AuthClientView(),
'/auth_company': (context) => const AuthCompanyView(),
'/reg_company': (context) => const RegCompanyView(),
'/client': (context) => const ClientView(),
'/company': (context) => const CompanyView(),
},
home: isLogOut ? const HomeView() : screenByUser[typeUser],
);
}
}
error in
setState(() {
isLogOut = false;
});
error screen
enter image description here

To solve this issue we have to clarify synchronous and asynchronous operations.
Initialating you widget with initState and next build method called one by one in synchronous way but getUser is asynchronous.
This is meant that you specify isLogOut before you setting the typeUser.
Instead of manually setting the isLogOut property just to change it to getter
bool get isLogOut => typeUser.isEmpty;
And you can guarantee the property will be correct all the time when you requests it.
Enjoy coding

Related

Remote end call

How to remote end call or broadcast in flutter for agora video call like, for example:
import 'package:flutter/material.dart';
class VideoCalling extends StatelessWidget {
const VideoCalling({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
late RtcEngine _engine;
return Scaffold(
body: ElevatedButton(onPressed: (){
if(_remoteUser.isFirst) async {
await _engine.remoteDestroy();
await _engine.destroy();
await _engine.leave().then(value) => Navigator.pop(context);
} else{
await _engine.destroy();
await _engine.leave().then(value) => Navigator.pop(context);
}
}, child: Text("End all calls")),
);
}
}

What is the purpose of authentication state unknown in flutter_bloc?

I was going through flutter_bloc documentation https://bloclibrary.dev/#/flutterlogintutorial, I saw that AuthenticationState has 3 states
enum AuthenticationStatus { authenticated, unauthenticated, unknown }
I couldn't understand the purpose of unknown state.
Here is the full code
bloc state
enum AuthenticationStatus { authenticated, unauthenticated, unknown }
class AuthenticationState extends Equatable {
const AuthenticationState._({
this.status = AuthenticationStatus.unknown,
this.user = User.empty,
});
const AuthenticationState.unknown() : this._();
const AuthenticationState.authenticated(User user)
: this._(status: AuthenticationStatus.authenticated, user: user);
const AuthenticationState.unauthenticated()
: this._(status: AuthenticationStatus.unauthenticated, user: User.empty);
final AuthenticationStatus status;
final User user;
#override
List<Object> get props => [status, user];
}
bloc_implementation
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
AuthenticationBloc({
#required AuthenticationRepository authenticationRepository,
}) : assert(authenticationRepository != null),
_authenticationRepository = authenticationRepository,
super(const AuthenticationState.unknown()) {
_userSubscription = _authenticationRepository.userStream.listen(
(user) => add(AuthenticationUserChanged(user)),
);
}
final AuthenticationRepository _authenticationRepository;
StreamSubscription<User> _userSubscription;
#override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if (event is AuthenticationUserChanged) {
yield _mapAuthenticationUserChangedToState(event);
} else if (event is AuthenticationLogoutRequested) {
unawaited(_authenticationRepository.logOut());
}
}
#override
Future<void> close() {
_userSubscription?.cancel();
return super.close();
}
AuthenticationState _mapAuthenticationUserChangedToState(
AuthenticationUserChanged event,
) =>
event.user != User.empty
? AuthenticationState.authenticated(event.user)
: const AuthenticationState.unauthenticated();
}
UI
import 'package:authentication_repository/authentication_repository.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_login/authentication/authentication.dart';
import 'package:flutter_login/home/home.dart';
// import 'package:flutter_login/login/login.dart';
import 'package:flutter_login/splash/splash.dart';
import 'package:flutter_login/splash/view/spash_page.dart';
import 'package:user_repository/user_repository.dart';
import 'authentication/bloc/authentication_bloc.dart';
import 'home/view/home_page.dart';
import 'login/view/login_page.dart';
class App extends StatelessWidget {
const App({
Key? key,
required this.authenticationRepository,
required this.userRepository,
}) : super(key: key);
final AuthenticationRepository authenticationRepository;
final UserRepository userRepository;
#override
Widget build(BuildContext context) {
return RepositoryProvider.value(
value: authenticationRepository,
child: BlocProvider(
create: (_) => AuthenticationBloc(
authenticationRepository: authenticationRepository,
userRepository: userRepository,
),
child: AppView(),
),
);
}
}
class AppView extends StatefulWidget {
#override
_AppViewState createState() => _AppViewState();
}
class _AppViewState extends State<AppView> {
final _navigatorKey = GlobalKey<NavigatorState>();
NavigatorState get _navigator => _navigatorKey.currentState!;
#override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: _navigatorKey,
builder: (context, child) {
return BlocListener<AuthenticationBloc, AuthenticationState>(
listener: (context, state) {
switch (state.status) {
case AuthenticationStatus.authenticated:
_navigator.pushAndRemoveUntil<void>(
HomePage.route(),
(route) => false,
);
break;
case AuthenticationStatus.unauthenticated:
_navigator.pushAndRemoveUntil<void>(
LoginPage.route(),
(route) => false,
);
break;
default:
break;
}
},
child: child,
);
},
onGenerateRoute: (_) => SplashPage.route(),
);
}
}
I think it is to display a splash screen, but we need to edit android and ios native code to display splash screen right?
Please help me to understand its purpose.

Error: Field '_webViewController' should be initialized because its type 'WebViewController' doesn't allow null

I am trying to run webview app which add some headers to website url ('cause I need to get device ID for push notifications service), but I get error:lib/main.dart:63:25: Error: Field '_webViewController' should be initialized because its type 'WebViewController' doesn't allow null.
Maybe someone can fix it? By the way, can someone check this code, what can be better here?
It's my first time creating Flutter app from scratch, so I need your opinio about this code :)
Main.dart code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:firebase_core/firebase_core.dart';
import 'notification.dart';
void main() async {
await init();
runApp(const MyApp());
}
Future init() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String notificationTitle = 'No Title';
String notificationBody = 'No Body';
String notificationData = 'No Data';
#override
void initState() {
final firebaseMessaging = FCM();
firebaseMessaging.setNotifications();
firebaseMessaging.streamCtlr.stream.listen(_changeData);
firebaseMessaging.bodyCtlr.stream.listen(_changeBody);
firebaseMessaging.titleCtlr.stream.listen(_changeTitle);
super.initState();
}
_changeData(String msg) => setState(() => notificationData = msg);
_changeBody(String msg) => setState(() => notificationBody = msg);
_changeTitle(String msg) => setState(() => notificationTitle = msg);
final Completer<WebViewController> _completer =
Completer<WebViewController>();
WebViewController _webViewController;
#override
Widget build(BuildContext context) {
_completer.future.then((controller) {
_webViewController = controller;
Map<String, String> header = {'cookie': 'device-id=12345'};
_webViewController.loadUrl('https://helpmate.lt/', headers: header);
});
return Scaffold(
body: Container(
child:
WebView(
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) async {
_completer.complete(controller);
})),
);
}
}

UI Not updating on bloc state change

I am new in using bloc library with freezed package. I have a scenario where a list of objects is coming from API is displayed. Now the list tile has a Marked as Fav button and clicking upon it a event is trigged and fav bool is toggled and state is emitted.
The Issue :
The value of the object is changed but the UI is not updated accordingly.
Main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_bloc_update/bloc/fakeapi_bloc.dart';
void main() {
runApp(
BlocProvider(
create: (context) => FakeapiBloc(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Scaffold(
body: SafeArea(child: MyHomePage()),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
context.read<FakeapiBloc>().add(const FakeapiEvent.loadData());
super.initState();
}
#override
Widget build(BuildContext context) {
return BlocBuilder<FakeapiBloc, FakeapiState>(
builder: (context, state) {
return state.map(
inital: (_) => const Center(
child: CircularProgressIndicator(),
),
loading: (_) => const Center(
child: CircularProgressIndicator(),
),
loaded: (state) {
return ListView.builder(itemBuilder: (ctx, pos) {
return ListTile(
title: Text(state.posts[pos].title),
trailing: IconButton(
onPressed: () {
context
.read<FakeapiBloc>()
.add(FakeapiEvent.markedFav(pos: pos));
},
icon: Icon(state.posts[pos].isFav
? Icons.favorite
: Icons.favorite_border_outlined),
),
);
});
},
error: (_) => const Center(
child: CircularProgressIndicator(),
),
);
},
);
}
}
Post.dart
import 'dart:convert';
List<Post> postFromJson(String str) =>
List<Post>.from(json.decode(str).map((x) => Post.fromJson(x)));
String postToJson(List<Post> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Post {
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
final int userId;
final int id;
final String title;
final String body;
bool isFav = false;
factory Post.fromJson(Map<String, dynamic> json) => Post(
userId: json["userId"],
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"body": body,
};
}
bloc.dart
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:freezed_bloc_update/post.dart';
import 'package:http/http.dart' as http;
part 'fakeapi_event.dart';
part 'fakeapi_state.dart';
part 'fakeapi_bloc.freezed.dart';
class FakeapiBloc extends Bloc<FakeapiEvent, FakeapiState> {
FakeapiBloc() : super(const FakeapiState.inital()) {
on<LoadData>(
(event, emit) async {
try {
emit(const FakeapiState.loading());
Uri uri = Uri.parse('https://jsonplaceholder.typicode.com/posts');
final response = await http.get(uri);
if (response.statusCode == 200) {
emit(FakeapiState.loaded(posts: postFromJson(response.body)));
} else {
emit(const FakeapiState.error(errorMessage: 'Api Call Failed'));
}
} catch (err) {
emit(const FakeapiState.error(errorMessage: 'Api Call Failed'));
}
},
);
on<MarkedFav>((event, emit) {
final previousState = state as Loaded;
previousState.posts[event.pos].isFav =
!previousState.posts[event.pos].isFav;
emit(FakeapiState.loaded(posts: [...previousState.posts]));
});
}
}
events.dart
part of 'fakeapi_bloc.dart';
#freezed
class FakeapiEvent with _$FakeapiEvent {
const factory FakeapiEvent.loadData() = LoadData;
const factory FakeapiEvent.markedFav({required int pos}) = MarkedFav;
}
states.dart
part of 'fakeapi_bloc.dart';
#freezed
class FakeapiState with _$FakeapiState {
const factory FakeapiState.inital() = Initial;
const factory FakeapiState.loading() = Loading;
const factory FakeapiState.loaded({required List<Post> posts}) = Loaded;
const factory FakeapiState.error({required String errorMessage}) = Error;
}
One solution which I did was keeping a bool variable(outside of model class) in state itself and clicking upon the fav toggling the bool value. Which is retriggering the UI update.
your Post class should be converted to a freezed class

Bloc doesn't provide the state flutter

I am new to Flutter, and bloc too. I got the idea, how bloc works. But When I create a simple app as the first step of my note app. The bloc doesn't give the data. This simple app has two screens. list screen and Notedetailscreen. Button in NoteDetailScreen tapped, data does not print to the text widget.
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:note_demo_bloc/bloc/note_bloc.dart';
import 'package:note_demo_bloc/list_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BlocProvider<NoteBloc>(
create: (context) => NoteBloc(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ListScreen(),
),
);
}
}
note_bloc.dart
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
part 'note_event.dart';
part 'note_state.dart';
class NoteBloc extends Bloc<NoteblocEvent, NoteblocState> {
NoteBloc() : super(NoteblocInitial());
#override
Stream<NoteblocState> mapEventToState(
NoteblocEvent event,
) async* {
if (event == NoteSaveEvent) {
yield NoteSaveState(state);
}
}
}
part of 'note_bloc.dart';
#immutable
abstract class NoteblocEvent {}
class NoteSaveEvent extends NoteblocEvent {
NoteSaveEvent(this.text);
final text;
}
note_state.dart
part of 'note_bloc.dart';
#immutable
abstract class NoteblocState {}
class NoteblocInitial extends NoteblocState {}
class NoteSaveState extends NoteblocState {
NoteSaveState(this.text);
final text;
}
list_screen.dart
import 'package:flutter/material.dart';
import 'package:note_demo_bloc/note_detail_screen.dart';
class ListScreen extends StatefulWidget {
const ListScreen({Key? key}) : super(key: key);
#override
_ListScreenState createState() => _ListScreenState();
}
class _ListScreenState extends State<ListScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Text('hi'),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => NoteDetailScreen(),
),
);
},
),
);
}
}
Note_detailscreen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:note_demo_bloc/bloc/note_bloc.dart';
class NoteDetailScreen extends StatefulWidget {
const NoteDetailScreen({Key? key}) : super(key: key);
#override
_NoteDetailScreenState createState() => _NoteDetailScreenState();
}
class _NoteDetailScreenState extends State<NoteDetailScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
ElevatedButton(
onPressed: () {
BlocProvider.of<NoteBloc>(context).add(NoteSaveEvent('hi'));
},
child: Text('click'),
),
BlocBuilder<NoteBloc, NoteblocState>(
builder: (context, state) {
return Text(state.toString());
},
)
],
),
);
}
}
Your bloc, state, and event looks fine. When you push screen you might need to use BlocProvider again. So try this:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:note_demo_bloc/bloc/note_bloc.dart';
import 'package:note_demo_bloc/list_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
NoteBloc _noteBloc = NoteBloc();
#override
Widget build(BuildContext context) {
return BlocProvider<NoteBloc>(
create: (context) => _noteBloc(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ListScreen(),
),
);
}
}
list_screen.dart
import 'package:flutter/material.dart';
import 'package:note_demo_bloc/note_detail_screen.dart';
class ListScreen extends StatefulWidget {
const ListScreen({Key? key}) : super(key: key);
#override
_ListScreenState createState() => _ListScreenState();
}
class _ListScreenState extends State<ListScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Text('hi'),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => BlocProvider.value(value: BlocProvider.of<NoteBloc>(context), child: NoteDetailScreen()),
),
);
},
),
);
}
}
Note_detailscreen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:note_demo_bloc/bloc/note_bloc.dart';
class NoteDetailScreen extends StatefulWidget {
const NoteDetailScreen({Key? key}) : super(key: key);
#override
_NoteDetailScreenState createState() => _NoteDetailScreenState();
}
class _NoteDetailScreenState extends State<NoteDetailScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
ElevatedButton(
onPressed: () {
BlocProvider.of<NoteBloc>(context).add(NoteSaveEvent('hi'));
},
child: Text('click'),
),
BlocBuilder<NoteBloc, NoteblocState>(
bloc: BlocProvider.of<NoteBloc>(context),
builder: (context, state) {
return Text(state.toString());
},
)
],
),
);
}
}
So, this is not an answer of your question but consider that as alternative (for future users of SO).
As state management is a free choice, and everyone could manage that as it’s “modus operandi“ this helper class “home made” could be a good choice.
import 'dart:async';
import 'dart:core';
class Method {
Method(this.name, this.params);
final String name;
final Map<String, Object> params;
}
class _Controller {
_Controller._();
static final Map<String, _Controller> _this = new Map<String, _Controller>();
final Map<String, Function(Method)> _funcs = new Map<String, Function(Method)>();
factory _Controller(String identifier) => _this.putIfAbsent(identifier, () => _Controller._());
Future<void> activateListener(String listenerId, Function(Method) function) async {
if (function != null)
_funcs.containsKey(listenerId) ? _funcs[listenerId] = function : _funcs.putIfAbsent(listenerId, () => function);
}
Future<void> deactivateListener(String listenerId) async =>
_funcs.removeWhere((String key, Function(Method) func) => key == listenerId);
Future<void> removeListener(String identifier) async =>
_this.removeWhere((String key, _Controller mClass) => key == identifier);
Future<void> callMethod(String methodName, {Map<String, Object> params}) async =>
Future.forEach(_funcs.values.where((v) => v != null), (func) async => func.call(Method(methodName, params)));
}
mixin MethodListener on Object {
_Controller _getController(String identifier) => _Controller(identifier ?? this.runtimeType.toString());
Future<void> activateListener({String identifier, List<String> identifiers}) async {
if (identifiers != null && identifiers.length > 0)
identifiers.forEach(
(String currentId) => _getController(currentId).activateListener(this.hashCode.toString(), onMethodListener));
else
_getController(identifier).activateListener(this.hashCode.toString(), onMethodListener);
}
Future<void> deactivateListener({String identifier, List<String> identifiers}) async {
if (identifiers != null && identifiers.length > 0)
identifiers.forEach((String currentId) => _getController(currentId).deactivateListener(this.hashCode.toString()));
else
_getController(identifier).deactivateListener(this.hashCode.toString());
}
Future<void> removeListener({String identifier}) async => _getController(identifier).removeListener(identifier);
void onMethodListener(Method method) async => null;
Future<void> callMethodOn(String identifier, String methodName, {Map<String, Object> params}) async =>
_getController(identifier).callMethod(methodName, params: params);
}
class MethodManager with MethodListener {
MethodManager._();
static MethodManager _this;
factory MethodManager() {
if (_this == null) _this = MethodManager._();
return _this;
}
Future<void> callMethodOnWidgets(List<String> identifiers, String methodName, {Map<String, Object> params}) async =>
identifiers.forEach((String currentId) => callMethodOn(currentId, methodName, params: params));
#override
Future<void> callMethodOn(String identifier, String methodName, {Map<String, Object> params}) async =>
super.callMethodOn(identifier, methodName, params: params);
}
then you can implements classes with “with MethodListener” as follows:
import 'package:flutter/material.dart';
import 'package:yourpackagehere/utils/XMethods.dart';
class Test extends StatefulWidget {
static const String NAME = "Test";
#override
createState() => _TestState();
}
class _TestState extends State<Test> with MethodListener {
String _ciao;
#override
void initState() {
super.initState();
this.activateListener(identifier: Test.NAME);
}
#override
void dispose() {
this.deactivateListener(identifier: Test.NAME);
super.dispose();
}
#override
Widget build(BuildContext context) {
return Container(child: Text(_ciao));
}
#override
void onMethodListener(Method method) {
switch (method.name) {
case "say_hello":
if (mounted) {
setState(() {
_ciao = method.params["my_string"];
});
}
break;
}
}
}
Usage:
From everywhere (from widgets or classes):
MethodManager().callMethodOn(Test.NAME, "say_hello", params: {"my_string": "SIAMO CAMPIONI DI EUROPA!!!"});