I have my BaseViewModel that is extending ChangeNotifer and then other viewModels extending the baseViewModel. The problem I am facing is when I call an api function inside init of baseViewModel it does works well and stores the value to the variables of that child viewModel but when I need to pass the values from UI and don't want the api function to be run in init rather I want to call it from the UI, the api works fine but doesn't stores the values to variables of child viewModel. Here is my BaseViewModel that is extending the ChangeNotifier:
abstract class BaseViewModel with ChangeNotifier {
bool _isLoading = false;
bool _isDisposed = false;
bool _isInitializeDone = false;
FutureOr<void> _initState;
BaseViewModel() {
_init();
}
FutureOr<void> init();
void _init() async {
this.isLoading = true;
_initState = init();
await _initState;
this._isInitializeDone = true;
this.isLoading = false;
}
void changeStatus() => isLoading = !isLoading;
void reloadState() {
if (!isLoading) notifyListeners();
}
@override
void dispose() {
_isDisposed = true;
super.dispose();
}
//Getters
FutureOr<void> get initState => _initState;
bool get isLoading => _isLoading;
bool get isDisposed => _isDisposed;
bool get isInitialized => _isInitializeDone;
//Setters
set isLoading(bool value) {
_isLoading = value;
scheduleMicrotask(() {
if (!_isDisposed) notifyListeners();
});
}
}
Here is my Child ViewModel extending the above baseViewModel:
class RoutesViewModel extends BaseViewModel {
RoutesViewModel({
required this.routesUseCase,
});
@override
FutureOr<void> init() async {
await getWeeklyRoutesByDriverID();
// await getWeeklyJobByRouteID(
// routeID: '34',
// driverID: '',
// memoryCache: 0,
// );
}
List<RoutesDetailModel> _routesDetailModel = [];
final RoutesUseCase routesUseCase;
String errorMessage = '';
List<JobDetailsModel> _jobDetailsModel = [];
RoutesDetailModel _routesDetailsModel = RoutesDetailModel.empty();
Future getWeeklyRoutesByDriverID() async {
changeStatus();
final response = await routesUseCase.getWeeklyRoutesByDriverID();
return response.fold(
(success) {
_routesDetailModel = success;
changeStatus();
return Left(
_routesDetailModel,
);
},
(r) {
changeStatus();
return Right(
errorMessage = r.message,
// showToast(
// message: r.message,
// context: context,
// ),
);
},
);
}
FutureOr<void> getWeeklyJobByRouteID({
required String routeID,
required String driverID,
required int memoryCache,
}) async {
changeStatus();
reloadState();
notifyListeners();
final response = await routesUseCase.getWeeklyJobsByRouteID(
routeID: routeID,
driverID: driverID,
memoryCache: memoryCache,
);
return response.fold(
(success) {
_jobDetailsModel = success;
changeStatus();
notifyListeners();
reloadState();
return Left(
_jobDetailsModel,
);
},
(r) {
changeStatus();
return Right(
Failure(
message: r.message,
status: r.status,
),
);
},
);
}
///Getters
int get routesCount => _routesDetailModel.length;
int get jobsCount => _jobDetailsModel.length;
String getData(int index) => _routesDetailModel[index].route.toString();
// int? getRouteID (int index) => _routesDetailModel[index].routeId;
List<RoutesDetailModel> getRoutesModel(int index) => [
_routesDetailModel[index],
];
}
You might see that one api call is being made in init and the other one is commented out. The first one works well and does store the values in _routesDetaiLModel but the other one doesn't as it requires params also I am calling it form UI. Here is how I am calling it from the UI:
class _JobsScreenState extends State<JobsScreen> {
@override
void initState() {
final provider = Provider.of<RoutesViewModel>(context, listen: false);
Future.delayed(
Duration(seconds: 3),
() {
provider.getWeeklyJobByRouteID(
routeID: widget.routesDetailModel[0].routeId.toString(),
driverID: '',
memoryCache: 0,
);
},
);
super.initState();
}
@override
Widget build(BuildContext context) {
// Provider.of<RoutesViewModel>(
// context,
// listen: true,
// );
return SafeArea(
child: Scaffold(
I have tried calling like this as well in init:
context.read<RoutesViewModel>().getWeeklyJobByRouteID( routeID: widget.routesDetailModel[0].routeId.toString(), driverID: '', memoryCache: 0, );
I also have tried using "with" keyword ChangeNotifer.
I have tried calling like this as well in init:
context.read<RoutesViewModel>().getWeeklyJobByRouteID( routeID: widget.routesDetailModel[0].routeId.toString(), driverID: '', memoryCache: 0, );
I am expecting the result to be stored in _jobsDetailModel and should give me the jobsCount. It does show me data being returned.