Search code examples
flutterasync-awaitaws-amplifyflutter-getx

Flutter: Async function in Getx Controller takes no effect when initialized


Updates:

2021/06/11 After hours of debugging yesterday, I confirmed that the problem is caused by aws amplify configuration: _configureAmplify(). Because the location of the amplify server was set wrong, so _configureAmplify() takes several seconds to work... and therefore, the readPost() function did not work on initialization, as it must run after _configureAmplify()...

2021/06/10I made changes to my code according to S. M. JAHANGIR's advice, and updated the question. The issue still presists. The value of posts is not updated when called in initialization and the data only shows up after reload. (if I commented out the _controller.readPost() in UI, the value of posts is always empty.


I have this page that loads information from aws amplify with getx implemented. However, I found out the readPost() async funtion in getx controller dart file is not reading from database, when the controller instance is initialized. I have to add a _controller.readPost() in UI file to make it work. And the data only shows up after a reload of that UI page...

Getx Controller dart file:

class ReadPostController extends GetxController {
  var isLoading = true.obs;
  var posts = <Posty>[].obs;

  @override
  void onInit() {
    _configureAmplify();
    await readPost();
    super.onInit();
    // print('show post return value: $posts');
  }

  void _configureAmplify() {
    final provider = ModelProvider();
    final dataStorePlugin = AmplifyDataStore(modelProvider: provider);
    AmplifyStorageS3 storage = new AmplifyStorageS3();
    AmplifyAuthCognito auth = new AmplifyAuthCognito();
    AmplifyAPI apiRest = AmplifyAPI();

    // Amplify.addPlugin(dataStorePlugin);
    Amplify..addPlugins([dataStorePlugin, storage, auth, apiRest]);
    Amplify.configure(amplifyconfig);
    print('Amplify configured');
  }    

// read all posts from databases
  Future readPost() async {
    try {
      isLoading(true);
      var result = await Amplify.DataStore.query(Posty.classType);
      print('finish loading request');
      result = result.sublist(1);
      posts.assignAll(result);
      // print(the value of posts is $posts');
    } finally {
      isLoading(false);
    }
  }

  @override
  void onClose() {
    // called just before the Controller is deleted from memory
    super.onClose();
  }
}

And in the UI part:

class TabBody extends StatelessWidget {
  TabBody({Key? key}) : super(key: key);
  final ReadPostController _controller = Get.put(ReadPostController());

  @override
  Widget build(BuildContext context) {
    _controller.readPost();//if commented out, _controller.post is empty
    return Container(
        child: Obx(
      () => Text('showing:${_controller.posts[1].title}'),
    ));
  }
}

In my understanding, the readPost() function should be called when the ReadPost_controller is initiallized. And the UI will update when the posts = <Posty>[].obs changes. Guys, what am I doing wrong here?


Solution

  • First, when you are calling readPost on onInit you are not awaiting. So change it to:

    onInit() async{
     ...
     await readPost();
     ... 
    }
    

    Secondly, posts is a RxList so you need to use the assignAll method to update it. Therefore, in your readPost method, instead of posts.value = reault you need to use posts.assignAll(result)

    • Calling from the UI works because readPost every time the build method is called by the Flutter framework and actually the UI shows the data from every previous call.