I'm implementing a flutter project using Getx library.
My current project has a format in which the response from the backend is recombined at the front end to the ui model and show on the screen. (Because the project's d-day is very close, so I could not change backend. I should just use a existing backend response).
Meanwhile, I was writing a code that some api call futures must keep the order.
To put it briefly, I receive a survey's result list and make a string list with survey's id (it is in the survey's result object).
After that, I receive a survey list and compare it to survey's result id list.
Through these courses, I will be able to know whether the survey has been completed or not from the survey list.
To implement this action, I declared two future, and I thought that the future was guaranteed the order by executing it with wait.
But nothing is changed in my view...
Below things are my codes.
class ExampleController extends GetxController {
final PreferenceManager _preferenceManager =
Get.find(tag: (PreferenceManager).toString());
/// ------------> related to survey values
final RxList<SurveyListUiModel> _rxSurveyListUiModelList = RxList.empty();
List<SurveyListUiModel> get surveyListUiModelList =>
_rxSurveyListUiModelList.toList();
final List<String> _surveyResultIdList = [];
void getSurveyConfigListWithSurveyResult() async{
Future<String> surveyResultListFuture =
_preferenceManager.getString('survey_result_list');
callDataService(
surveyResultListFuture,
onSuccess: _handleSurveyResultListResponseSuccess,
);
Future<String> surveyListFuture =
_preferenceManager.getString('survey_list');
await callDataService(
surveyConfigListFuture,
onSuccess: _handleSurveyListResponseSuccess,
);
setListLoading(false);
}
void _handleSurveyResultListResponseSuccess(String response) {
List<dynamic> list = jsonDecode(response) as List<dynamic>;
for (var element in list) {
SurveyConfigResponse surveyConfigResponse = SurveyConfigResponse.fromJson(
element['survey_config'] as Map<String, dynamic>);
_surveyResultIdList.add(surveyConfigResponse.id);
}
}
void _handleSurveyListResponseSuccess(String response) {
List<dynamic> list = jsonDecode(response) as List<dynamic>;
for (var element in list) {
SurveyConfigResponse surveyConfigResponse =
SurveyConfigResponse.fromJson(element as Map<String, dynamic>);
surveyListUiModelList.add(SurveyListUiModel(
surveyConfigId: surveyConfigResponse.id,
surveyConfigTitle: surveyConfigResponse.title,
isDiagnosed: _surveyResultIdList.contains(surveyConfigResponse.id),
));
_rxSurveyListUiModelList.refresh();
}
}
/// ------------> related to survey values
@override
void onInit() {
getSurveyConfigListWithSurveyResult();
super.onInit();
}
}
// callDataService method
dynamic callDataService<T>(
Future<T> future, {
Function(Exception exception)? one rror,
Function(T response)? onSuccess,
Function? onStart,
Function? onComplete,
}) async {
Exception? _exception;
onStart == null ? showLoading() : onStart();
try {
final T response = await future;
if (onSuccess != null) onSuccess(response);
onComplete == null ? hideLoading() : onComplete();
return response;
} on ServiceUnavailableException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} on UnauthorizedException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} on TimeoutException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} on NetworkException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} on JsonFormatException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} on NotFoundException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} on ApiException catch (exception) {
_exception = exception;
} on AppException catch (exception) {
_exception = exception;
showErrorMessage(exception.message);
} catch (error) {
_exception = AppException(message: "$error");
logger.e("Controller>>>>>> error $error");
}
if (onError != null) one rror(_exception);
onComplete == null ? hideLoading() : onComplete();
}
// example view
class ExampleView extends GetView<ExampleController> {
@override
Widget body(BuildContext context) {
return Obx(() => Text(controller.surveyListUiModelList.length.toString()));
}
}
What is the missing point in my codes..?
Edit 1
With obove code, the lists in the _handle~~~Success
method has a right value.
CodePudding user response:
A bit tricky to follow your code, but I think you should be awaiting the first call to callDataService(...)
I.e. this:
callDataService(
surveyLifeResultListFuture,
onSuccess: _handleSurveyResultListResponseSuccess,
);
should be:
await callDataService(
surveyLifeResultListFuture,
onSuccess: _handleSurveyResultListResponseSuccess,
);
CodePudding user response:
Oh It's my mistake. The method callDataService
is an already synchronized method...
So I did not have to consider asynchronization.
The order in which the code was written was applied in the order of execution.
A real problem was RxList
.
In my question code, I writed a getter method of RxList like this.
List<SurveyListUiModel> get surveyListUiModelList => _rxSurveyListUiModelList.toList();
The toList() method is just extracting a Growable List from RxList.
it's code is here.
List<E> toList({bool growable = true}) {
if (this.isEmpty) return List<E>.empty(growable: growable);
var first = this[0];
var result = List<E>.filled(this.length, first, growable: growable);
for (int i = 1; i < this.length; i ) {
result[i] = this[i];
}
return result;
}
And, with that extracted list(copy the past state of RxList), I tried adding new items...
So, the obx widget in exampleView that is observing RxList
did not response the past extracted list.
To solve this question, I changed my add items
code with RxList
keeping others in same.
before
void _handleSurveyConfigListResponseSuccess(String response) {
List<dynamic> list = jsonDecode(response) as List<dynamic>;
for (var element in list) {
SurveyConfigResponse surveyConfigResponse =
SurveyConfigResponse.fromJson(element as Map<String, dynamic>);
surveyListUiModelList.add(SurveyListUiModel(
surveyConfigId: surveyConfigResponse.id,
surveyConfigTitle: surveyConfigResponse.title,
isDiagnosed: _surveyResultIdList.contains(surveyConfigResponse.id),
));
}
_rxSurveyListUiModelList.refresh();
}
after
void _handleSurveyConfigListResponseSuccess(String response) {
List<dynamic> list = jsonDecode(response) as List<dynamic>;
for (var element in list) {
SurveyConfigResponse surveyConfigResponse =
SurveyConfigResponse.fromJson(element as Map<String, dynamic>);
_rxSurveyListUiModelList.add(SurveyListUiModel(
surveyConfigId: surveyConfigResponse.id,
surveyConfigTitle: surveyConfigResponse.title,
isDiagnosed: _surveyResultIdList.contains(surveyConfigResponse.id),
));
}
_rxSurveyListUiModelList.refresh();
}