Search code examples
flutterparse-platform

Flutter Parse_server_SDK LateInitializationError: Field '_instance@597240915' on ParseObject when query data


I want to query data with Parse_server_sdk but i get this error [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: LateInitializationError: Field '_instance@597240915' has not been initialized.

it only happens when I call the method on initState() but if I test it when onPressed in elevatedButton it can get called without error. I don't know what the problem is, please someone help me.

this is the home screen code where the query is called :

import 'package:flutter/material.dart';
import 'package:flutter_simple_cms/api/parse_services.dart';
import 'package:flutter_simple_cms/screens/update_post_screen.dart';
import 'package:flutter_simple_cms/widgets/show_drawer.dart';
import 'package:flutter_simple_cms/widgets/show_snackbar.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<ParseObject> getPostList = [];

  Future<List<ParseObject>>? testGetPost;
  bool isDeleting = false;

  @override
  void initState() {
    super.initState();
    getDataTest();
  }

  void getDataTest() async {
    testGetPost = ParseService().getPostsFuture();
    print(testGetPost);
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Home'),
        ),
        drawer: showDrawer(context),
        body: testBody(),
      ),
    );
  }

  Widget testBody() {
    return SizedBox(
      height: MediaQuery.of(context).size.height,
      width: MediaQuery.of(context).size.width,
      child: Center(
        child: ElevatedButton(
          child: const Text('test'),
          onPressed: () {
            getDataTest();
          },
        ),
      ),
    );
  }

  Widget _body() {
    return SizedBox(
      height: MediaQuery.of(context).size.height,
      width: MediaQuery.of(context).size.width,
      child: StreamBuilder<List<ParseObject>>(
        initialData: getPostList,
        stream: ParseService().getPosts(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(
              child: SizedBox(
                height: 75.0,
                width: 75.0,
                child: CircularProgressIndicator(),
              ),
            );
          } else if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.hasError) {
              return Center(
                  child: ElevatedButton(
                child: const Text("Refresh"),
                onPressed: () {
                  setState(() {});
                },
              ));
            }
            if (snapshot.hasData) {
              if (snapshot.data!.isEmpty) {
                return const Center(
                  child: Text('NO DATA', style: TextStyle(fontSize: 36.0)),
                );
              }
              return ListView.builder(
                padding: const EdgeInsets.only(top: 10.0),
                itemCount: snapshot.hasData ? snapshot.data!.length : 1,
                itemBuilder: (BuildContext context, int index) {
                  if (snapshot.data!.isEmpty) {
                    return SizedBox(
                      width: MediaQuery.of(context).size.width,
                      height: MediaQuery.of(context).size.height,
                      child: const Center(
                        child: Text(
                          'Data is Empty!',
                          style: TextStyle(fontSize: 36.0),
                        ),
                      ),
                    );
                  }
                  final postData = snapshot.data![index];
                  ParseFile? postImageCover =
                      snapshot.data![index].get<ParseFile>('postImageCover');
                  final postTitle = postData.get<String>('postTitle')!;
                  final postContent = postData.get<String>('postContent')!;
                  return Card(
                    elevation: 7.0,
                    clipBehavior: Clip.hardEdge,
                    shape: RoundedRectangleBorder(
                      side: BorderSide(
                        color: Theme.of(context).colorScheme.primaryContainer,
                        width: 1.5,
                      ),
                      borderRadius:
                          const BorderRadius.all(Radius.circular(15.0)),
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Container(
                            alignment: Alignment.centerRight,
                            child: PopupMenuButton(
                              itemBuilder: (context) {
                                return [
                                  PopupMenuItem(
                                    value: 0,
                                    child: Row(
                                      children: const [
                                        Icon(Icons.edit_note),
                                        SizedBox(
                                          // sized box with width 10
                                          width: 10,
                                        ),
                                        Text("Edit post")
                                      ],
                                    ),
                                  ),
                                  PopupMenuItem(
                                    value: 1,
                                    child: Row(
                                      children: const [
                                        Icon(Icons.delete),
                                        SizedBox(
                                          // sized box with width 10
                                          width: 10,
                                        ),
                                        Text("Delete post")
                                      ],
                                    ),
                                  ),
                                ];
                              },
                              onSelected: (value) {
                                if (value == 0) {
                                  Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                      builder: (context) =>
                                          UpdatePost(postObject: postData),
                                    ),
                                  );
                                } else {
                                  isDeleting = true;
                                  ParseService()
                                      .deletePost(postData.objectId)
                                      .then((response) {
                                    if (response.success) {
                                      setState(() => isDeleting = false);
                                      showSnackbar(
                                        context,
                                        'Post Deleted!',
                                        Colors.greenAccent,
                                        Icons.check_circle_outline,
                                        Colors.greenAccent,
                                      );
                                    } else {
                                      isDeleting = false;
                                      showSnackbar(
                                        context,
                                        response.error?.message,
                                        Colors.red,
                                        Icons.error_outline,
                                        Colors.red,
                                      );
                                    }
                                  });
                                }
                              },
                            ),
                          ),
                          addSpace(10.0),
                          Visibility(
                            visible: postImageCover != null,
                            child: SizedBox(
                              width: MediaQuery.of(context).size.width,
                              height: 300.0,
                              child: postImageCover == null
                                  ? null
                                  : Image.network(
                                      loadingBuilder:
                                          (context, child, loadingProgress) {
                                        if (loadingProgress == null) {
                                          return child;
                                        }
                                        return const Center(
                                          child: SizedBox(
                                            height: 50.0,
                                            width: 50.0,
                                            child: CircularProgressIndicator(),
                                          ),
                                        );
                                      },
                                      postImageCover.url!,
                                      fit: BoxFit.cover,
                                    ),
                            ),
                          ),
                          addSpace(10.0),
                          Text(
                            postTitle,
                            textAlign: TextAlign.center,
                            style: const TextStyle(fontSize: 20.0),
                          ),
                          addSpace(10.0),
                          Text(
                            postContent,
                            textAlign: TextAlign.center,
                            style: const TextStyle(fontSize: 16.0),
                          ),
                          addSpace(5.0),
                        ],
                      ),
                    ),
                  );
                },
              );
            } else {
              return const Center(
                child: Text('NO DATA', style: TextStyle(fontSize: 36.0)),
              );
            }
          } else {
            return Text('State: ${snapshot.connectionState}');
          }
        },
      ),
    );
  }

  Widget addSpace(double? heightVal) => SizedBox(height: heightVal);
}

this is the query method that the homescreen called :

Future<List<ParseObject>> getPostsFuture() async {
    QueryBuilder<ParseObject> queryPosts =
        QueryBuilder<ParseObject>(ParseObject('PostList'));
    final ParseResponse apiResponse = await queryPosts.query();

    if (apiResponse.success && apiResponse.results != null) {
      return Future.value(apiResponse.results as List<ParseObject>);
    } else {
      return [];
    }
  }

I also tried to put it on FutureBuilder thinking that the query cannot get called in initState which is weird because a long time ago on the older version of flutter and Parse_server_sdk there is no problem with my other app when called the query in initState but even using future builder still the query did not get called on the first build it got stuck on the snapshot.hasError. on the code, I provide change it to streamBuilder but it's also the same got stuck when first build so I just put a button to refresh to get the data on the first launch/build


Solution

  • I manage to fix it myself, so i will give my answer for anyone that got the same problem as like this. so first the problem with the class ParseObject got LateInitializationError is because the Parse.initialize is not yet finish but the class homescreen.dart immediately got called maybe it's because the Parse.initialize is on his own class. so for anyone who are the same like me that you put the Parse.initialize on it's own class, this could be help if you got the same problem like this.

    so to fix it first i change the class where the Parse.initialize is on to be Future to return value of the Parse class.

    like this :

    import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
    
    class ApiServices {
      // testing database
      final String keyApplicationId = "Your App ID";
      final String keyClientKey = "Your client key";
      final String keyParseServerUrl = "https://parseapi.back4app.com/";
    
      Future<Parse> initialize() async { //on this line
        return Parse().initialize(
          keyApplicationId,
          keyParseServerUrl,
          debug: true,
          clientKey: keyClientKey,
          coreStore: await CoreStoreSharedPrefsImp.getInstance(),
        );
      }
    }
    

    and after that on the main.dart file you must change the Parse.initialize in the void main().

    like this :

    void main() {
      WidgetsFlutterBinding.ensureInitialized();
      ApiServices().initialize().then((value) {//on this line
        if (value.hasParseBeenInitialized()) {//and you need to add this
          runApp(const MyApp());
        }
      });
    }
    

    I hope my answer could be a help