skip to Main Content

whenever i want to edit or add a note on my home page it navigates to (edit note page ) or (add note page) then click on (update note button) or ( add note button) , it update changes on firebase smoothly but on my flutter app i have to hot restart once again so updates take place, what i can do to update the notes on my homepage without having to run or hot restart the app again,

everything work great unless notes on homepage won`t update unless i hot-restart the app again

main :

    import 'package:firebase_wael/crud/add_note.dart';
import 'package:firebase_wael/crud/edit_note.dart';
import 'package:firebase_wael/home_page.dart';
import 'package:firebase_wael/auth/signin_page.dart';

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'auth/signup_page.dart';

bool? isSignedIn;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  var user = FirebaseAuth.instance.currentUser;
  if (user == null) {
    isSignedIn = false;
  } else {
    isSignedIn = true;
  }
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      builder: EasyLoading.init(),
      home: HomePage(),
      //initialRoute: isSignedIn == true ? 'home' : 'signup',
      routes: {
        'signup': (context) => SignUpPage(),
        'home': (context) => HomePage(),
        'signin': (context) => SignInPage(),
        'addnote': (context) => AddNote(),
        'editnote': (context) => EditNote(),
      },
    );
  }
}

homepage :

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_wael/crud/edit_note.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  CollectionReference notes = FirebaseFirestore.instance.collection('notes');
  var currentUser = FirebaseAuth.instance.currentUser;

  getUser() {
    var user = FirebaseAuth.instance.currentUser;
    print(user?.email);
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
        actions: [
          IconButton(
            onPressed: () async {
              await FirebaseAuth.instance.signOut();
              Get.offAllNamed('signin');
            },
            icon: Icon(Icons.exit_to_app_outlined),
          ),
        ],
      ),
      body: FutureBuilder(
          future: notes.where('userId', isEqualTo: currentUser!.uid).get(),
          builder: (context, AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                  itemCount: snapshot.data.docs.length,
                  itemBuilder: (context, index) {
                    return ListNote(
                      snapshot: snapshot,
                      index: index,
                      docId: snapshot.data.docs[index].reference.id,
                    );
                  });
            }
            if (snapshot.hasError) {
              return Text('Error');
            }
            return Center(child: CircularProgressIndicator());
          }),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Get.toNamed('addnote');
        },
      ),
    );
  }
}

class ListNote extends StatelessWidget {
  final docId;
  final AsyncSnapshot snapshot;
  final int index;
  const ListNote({
    Key? key,
    required this.snapshot,
    required this.index,
    this.docId,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Row(
        children: [
          Expanded(
            flex: 1,
            child: Image.network(
              snapshot.data.docs[index]['imageUrl'],
              height: 100.0,
              fit: BoxFit.fitHeight,
            ),
          ),
          Expanded(
            flex: 2,
            child: ListTile(
              title: Text('${snapshot.data.docs[index]['title']}'),
              subtitle: Text('${snapshot.data.docs[index]['note']}'),
            ),
          ),
          Expanded(
            child: Row(
              children: [
                IconButton(
                  onPressed: () {
                    Get.to(
                      () => EditNote(
                        docId: docId,
                        snapshot: snapshot.data.docs[index],
                      ),
                    );
                  },
                  icon: Icon(
                    Icons.edit,
                    color: Colors.blue,
                  ),
                ),
                IconButton(
                  onPressed: () {},
                  icon: Icon(
                    Icons.delete,
                    color: Colors.red,
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}

add note page :

import 'dart:io';
import 'dart:math';
import 'package:awesome_dialog/awesome_dialog.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:get/get.dart';

import '../components/loading.dart';

class AddNote extends StatefulWidget {
  const AddNote({Key? key}) : super(key: key);

  @override
  State<AddNote> createState() => _AddNoteState();
}

class _AddNoteState extends State<AddNote> {
  GlobalKey<FormState> formState = GlobalKey();
  String? title;
  String? note;
  String? imageUrl;
  File? file;
  late Reference storageRef;
  CollectionReference noteRef = FirebaseFirestore.instance.collection('notes');
  bool loading = false;

  addNote() async {
    //// <=== to force adding an image ===> ////
    if (file == null) {
      return AwesomeDialog(
              context: this.context,
              title: 'warning',
              body: Text('Please choose image'),
              dialogType: DialogType.WARNING,
              padding: EdgeInsets.all(20))
          .show();
    }
    var formData = formState.currentState;

    if (formData!.validate()) {
      formData.save();

      setState(() {
        loading = true;
      });

      await storageRef.putFile(file!);

      imageUrl = await storageRef.getDownloadURL();

      await noteRef.add({
        'title': title,
        'note': note,
        'imageUrl': imageUrl,
        'userId': FirebaseAuth.instance.currentUser!.uid,
      });
    }
    Get.back();
  }

  @override
  Widget build(BuildContext context) {
    return loading
        ? Loading()
        : Scaffold(
            appBar: AppBar(
              title: Text('Add Note'),
            ),
            body: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Form(
                    key: formState,
                    child: Column(
                      children: [
                        TextFormField(
                          validator: (value) {
                            if (value!.length > 30) {
                              return 'Title can't be larger than 30 letters';
                            }
                            if (value.length < 3) {
                              return 'Title can't be less than 3 letters';
                            }

                            return null;
                          },
                          onSaved: (value) {
                            title = value;
                          },
                          maxLength: 30,
                          decoration: InputDecoration(
                            labelText: 'Title',
                            prefixIcon: Icon(Icons.note),
                          ),
                        ),
                        TextFormField(
                          validator: (value) {
                            if (value!.length > 200) {
                              return 'Note can't be larger than 200 letters';
                            }
                            if (value.length < 10) {
                              return 'Note can't be less than 10 letters';
                            }

                            return null;
                          },
                          onSaved: (value) {
                            note = value;
                          },
                          maxLength: 200,
                          maxLines: 4,
                          minLines: 1,
                          decoration: InputDecoration(
                            labelText: 'Note',
                            prefixIcon: Icon(Icons.note),
                          ),
                        ),
                        SizedBox(
                          height: 15,
                        ),
                        ElevatedButton(
                          onPressed: () {
                            showBottom(context);
                          },
                          child: Padding(
                            padding: const EdgeInsets.all(10.0),
                            child: Text(
                              'Add Image',
                              style: TextStyle(fontSize: 16),
                            ),
                          ),
                        ),
                        SizedBox(
                          height: 15,
                        ),
                        ElevatedButton(
                          onPressed: () async {
                            await addNote();
                          },
                          child: Padding(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 24.0, vertical: 14),
                            child: Text(
                              'Add Note',
                              style: TextStyle(
                                  fontSize: 20, fontWeight: FontWeight.bold),
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                )
              ],
            ),
          );
  }

  Future showBottom(context) async {
    await showModalBottomSheet(
        context: context,
        builder: (context) {
          return Container(
            padding: EdgeInsets.all(20),
            height: MediaQuery.of(context).size.height * 0.25,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Please choose your image:',
                  style: TextStyle(
                      fontSize: 22,
                      fontWeight: FontWeight.bold,
                      color: Colors.grey.shade700),
                ),
                SizedBox(
                  height: 20,
                ),
                GestureDetector(
                  onTap: () async {
                    var pickedImage = await ImagePicker()
                        .pickImage(source: ImageSource.gallery);
                    if (pickedImage == null) return;

                    setState(() {
                      file = File(pickedImage.path);
                    });

                    var imageName = basename(pickedImage.path);

                    var random = Random().nextInt(100000000);

                    imageName = '$random$imageName';

                    storageRef =
                        FirebaseStorage.instance.ref('images').child(imageName);

                    Get.back();
                  },
                  child: Container(
                    width: double.infinity,
                    child: Row(
                      children: [
                        Icon(
                          Icons.photo_outlined,
                          size: 30,
                        ),
                        SizedBox(
                          width: 15,
                        ),
                        Text(
                          'From Gallery',
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.w700),
                        ),
                      ],
                    ),
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                GestureDetector(
                  onTap: () async {
                    var pickedImage = await ImagePicker()
                        .pickImage(source: ImageSource.camera);
                    if (pickedImage == null) return;

                    setState(() {
                      file = File(pickedImage.path);
                    });
                    var imageName = basename(pickedImage.path);
                    var random = Random().nextInt(100000000);
                    imageName = '$random$imageName';

                    storageRef =
                        FirebaseStorage.instance.ref('images').child(imageName);
                    Get.back();
                  },
                  child: Container(
                    width: double.infinity,
                    child: Row(
                      children: [
                        Icon(
                          Icons.camera_alt_outlined,
                          size: 30,
                        ),
                        SizedBox(
                          width: 15,
                        ),
                        Text(
                          'From Camera',
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.w700),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );
        });
  }
}

edit note page:

import 'dart:io';
import 'dart:math';

import 'package:cloud_firestore/cloud_firestore.dart';

import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:get/get.dart';

import '../components/loading.dart';

class EditNote extends StatefulWidget {
  final docId;
  final snapshot;
  const EditNote({
    Key? key,
    this.docId,
    this.snapshot,
  }) : super(key: key);

  @override
  State<EditNote> createState() => _EditNoteState();
}

class _EditNoteState extends State<EditNote> {
  GlobalKey<FormState> formState = GlobalKey();
  String? title;
  String? note;
  String? imageUrl;
  File? file;
  late Reference storageRef;
  CollectionReference noteRef = FirebaseFirestore.instance.collection('notes');
  bool loading = false;

  editNote() async {
    var formData = formState.currentState;
    //// <=== to force adding an image ===> ////
    if (file == null) {
      if (formData!.validate()) {
        formData.save();

        setState(() {
          loading = true;
        });

        await noteRef.doc(widget.docId).update({
          'title': title,
          'note': note,
        });
        Get.back();
      }
    } else {
      if (formData!.validate()) {
        formData.save();

        setState(() {
          loading = true;
        });

        await storageRef.putFile(file!);

        imageUrl = await storageRef.getDownloadURL();

        await noteRef.doc(widget.docId).update({
          'title': title,
          'note': note,
          'imageUrl': imageUrl,
        });
        Get.back();
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return loading
        ? Loading()
        : Scaffold(
            appBar: AppBar(
              title: Text('Edit Note'),
            ),
            body: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Form(
                    key: formState,
                    child: Column(
                      children: [
                        TextFormField(
                          initialValue: widget.snapshot['title'],
                          validator: (value) {
                            if (value!.length > 30) {
                              return 'Title can't be larger than 30 letters';
                            }
                            if (value.length < 3) {
                              return 'Title can't be less than 3 letters';
                            }

                            return null;
                          },
                          onSaved: (value) {
                            setState(() {
                              title = value;
                            });
                          },
                          maxLength: 30,
                          decoration: InputDecoration(
                            labelText: 'Title',
                            prefixIcon: Icon(Icons.note),
                          ),
                        ),
                        TextFormField(
                          initialValue: widget.snapshot['note'],
                          validator: (value) {
                            if (value!.length > 200) {
                              return 'Note can't be larger than 200 letters';
                            }
                            if (value.length < 10) {
                              return 'Note can't be less than 10 letters';
                            }

                            return null;
                          },
                          onSaved: (value) {
                            setState(() {
                              note = value;
                            });
                          },
                          maxLength: 200,
                          maxLines: 4,
                          minLines: 1,
                          decoration: InputDecoration(
                            labelText: 'Note',
                            prefixIcon: Icon(Icons.note),
                          ),
                        ),
                        SizedBox(
                          height: 15,
                        ),
                        ElevatedButton(
                          onPressed: () {
                            showBottom(context);
                          },
                          child: Padding(
                            padding: const EdgeInsets.all(10.0),
                            child: Text(
                              'Edit Image',
                              style: TextStyle(fontSize: 16),
                            ),
                          ),
                        ),
                        SizedBox(
                          height: 15,
                        ),
                        ElevatedButton(
                          onPressed: () async {
                            await editNote();
                          },
                          child: Padding(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 24.0, vertical: 14),
                            child: Text(
                              'update note',
                              style: TextStyle(
                                  fontSize: 20, fontWeight: FontWeight.bold),
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                )
              ],
            ),
          );
  }

  Future showBottom(context) async {
    await showModalBottomSheet(
        context: context,
        builder: (context) {
          return Container(
            padding: EdgeInsets.all(20),
            height: MediaQuery.of(context).size.height * 0.25,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Please choose your image:',
                  style: TextStyle(
                      fontSize: 22,
                      fontWeight: FontWeight.bold,
                      color: Colors.grey.shade700),
                ),
                SizedBox(
                  height: 20,
                ),
                GestureDetector(
                  onTap: () async {
                    var pickedImage = await ImagePicker()
                        .pickImage(source: ImageSource.gallery);
                    if (pickedImage == null) return;

                    setState(() {
                      file = File(pickedImage.path);
                    });

                    var imageName = basename(pickedImage.path);

                    var random = Random().nextInt(100000000);

                    imageName = '$random$imageName';

                    storageRef =
                        FirebaseStorage.instance.ref('images').child(imageName);

                    Get.back();
                  },
                  child: Container(
                    width: double.infinity,
                    child: Row(
                      children: [
                        Icon(
                          Icons.photo_outlined,
                          size: 30,
                        ),
                        SizedBox(
                          width: 15,
                        ),
                        Text(
                          'From Gallery',
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.w700),
                        ),
                      ],
                    ),
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                GestureDetector(
                  onTap: () async {
                    var pickedImage = await ImagePicker()
                        .pickImage(source: ImageSource.camera);
                    if (pickedImage == null) return;

                    setState(() {
                      file = File(pickedImage.path);
                    });
                    var imageName = basename(pickedImage.path);
                    var random = Random().nextInt(100000000);
                    imageName = '$random$imageName';

                    storageRef =
                        FirebaseStorage.instance.ref('images').child(imageName);
                    Get.back();
                  },
                  child: Container(
                    width: double.infinity,
                    child: Row(
                      children: [
                        Icon(
                          Icons.camera_alt_outlined,
                          size: 30,
                        ),
                        SizedBox(
                          width: 15,
                        ),
                        Text(
                          'From Camera',
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.w700),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );
        });
  }
}

loading spinkit page :

import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

class Loading extends StatelessWidget {
  const Loading({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: SpinKitChasingDots(
        color: Colors.red,
        size: 50.0,
      ),
    );
  }
}

sorry if i have any language mistakes .
thank you alot

EDIT now im able to update document on both firebase and flutter app using streamBuilder instead of futureBuilder, but now im having another problem which is : i need to stream document for specific userId , how to filter StreamBuilder ?

2

Answers


  1. Chosen as BEST ANSWER

    UPDATE

    i fixed all the issues by using FutureBuilder inside StreamBuilder so i can filter the StreamBuilder to specific userId :

    body: StreamBuilder(
          stream: notesStream,
          builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasData) {
              return FutureBuilder(
                  future:
                      notes.where('userId', isEqualTo: currentUser!.uid).get(),
                  builder: (context, AsyncSnapshot snapshot2) {
                    if (snapshot2.hasData) {
                      return ListView.builder(
                          itemCount: snapshot2.data!.docs.length,
                          itemBuilder: (context, index) {
                            return ListNote(
                              snapshot: snapshot2,
                              index: index,
                              docId: snapshot2.data!.docs[index].reference.id,
                              delete: () async {
                                await notes
                                    .doc(snapshot2
                                        .data!.docs[index].reference.id)
                                    .delete();
                                await FirebaseStorage.instance.refFromURL(snapshot2
                                    .data!.docs[index]['imageUrl']).delete();
                              },
                            );
                          });
                    }
                    if (snapshot2.hasError) {
                      print('ERROR');
                    }
                    if (snapshot2.connectionState == ConnectionState.waiting) {
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    }
                    return Center(
                      child: CircularProgressIndicator(),
                    );
                  });
            }
            if (snapshot.hasError) {
              print('errot');
            }
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
            return Center(
              child: CircularProgressIndicator(),
            );
          }),
    

    thx guys :)


  2. Make sure to use stream builder to get continuous updates of data. Please share the updated code & the problem you are getting.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search