Home > Mobile >  Unable to update new data in Listview Flutter
Unable to update new data in Listview Flutter

Time:10-12

Hey guys I am new to flutter, I have been trying to build a mock app that shows a feed it works fine using the mock data, but when I try to add new input data it gets added but doesn't get updated, please help me, I totally understand that my mistake can be super trivial and foolish but I have been stuck for weeks, here is the code. This is the screen where everything is displayed

import 'package:deep_pocket/models/data_feed.dart';
import 'package:deep_pocket/models/mock_data.dart';
import 'package:deep_pocket/widgets/menu_buttons.dart';
import 'package:deep_pocket/widgets/post_widget.dart';
import 'package:deep_pocket/screens/user_input.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';

class feedScreen extends StatefulWidget {
  @override
  State<feedScreen> createState() => _feedScreenState();
}

class _feedScreenState extends State<feedScreen> {
  int filter = 0;

  void updateFilter(tx, context) {
    setState(() {
      filter = tx;
    });

    Navigator.of(context).pop();
  }

  void filterSheet(ctx) {
    showModalBottomSheet(
        context: ctx,
        builder: (ctx) => Container(
              height: 300,
              child: SingleChildScrollView(
                  child: Container(
                height: 280,
                child: ListView.builder(
                    itemCount: Tag.length,
                    itemBuilder: (ctx, i) => TextButton(
                          onPressed: () {
                            return updateFilter(i, context);
                          },
                          child: Text(Tag[i]),
                        )),
              )),
            ));
  }

  @override
  Widget build(BuildContext context) {
    var posts = Provider.of<mockData>(context).items;

    print(posts.length);
    if (filter != 0) {
      posts = posts.where((i) => i.tag == filter).toList();
    }
    return Scaffold(
      // drawer: Drawer(
      //     // Populate the Drawer in the next step.
      //     ),
      appBar: AppBar(
        title: const Text("Home"),
        actions: [
          TextButton(
              onPressed: () => {filterSheet(context)},
              child: const Text(
                "Filters",
                style: TextStyle(color: Colors.white),
              ))
        ],
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            menuButtons(),
            Container(
              padding: const EdgeInsets.all(8),
              child: ListView.builder(
                  shrinkWrap: true,
                  physics: NeverScrollableScrollPhysics(),
                  itemCount: posts.length,
                  itemBuilder: (ctx, i) => postWidget(post: posts[i])),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
          onPressed: () {
            Navigator.pushNamed(context, userInput.route);
          },
          child: const Icon(Icons.add)),
    );
  }
}
 

This is where I am handling Input

import 'package:deep_pocket/models/data_feed.dart';
import 'package:deep_pocket/models/mock_data.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class userInput extends StatefulWidget {
  static const route = '/user-input';

  @override
  _userInputState createState() => _userInputState();
}

class _userInputState extends State<userInput> {
  var _chosenValue = 'all';
  final titleController = TextEditingController();
  final bodyController = TextEditingController();

  
  void submitted() {
    String titleCheck = titleController.text;
    String bodyCheck = bodyController.text;
    int tag = Tag.indexOf(_chosenValue);
    if (titleCheck.isEmpty || bodyCheck.length < 10) {
      return;
    }

    final newPost = dataFeed(
      imgsrc: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
      name: "Priyam ",
      title: titleCheck,
      text: bodyCheck,
      tag: tag,
    );
    titleController.dispose();
    bodyController.dispose();
    Provider.of<mockData>(context, listen: false).addPost(newPost);
    Navigator.of(context).pop();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton.extended(
        onPressed: submitted,
        label: const Text("SUBMIT"),
      ),
      appBar: AppBar(
        title: Text("New Post"),
      ),
      body: Container(
        child: Column(
          children: [
            TextField(
              controller: titleController,
              decoration: const InputDecoration(
                label: Text("Title"),
                enabledBorder: OutlineInputBorder(),
              ),
            ),
            TextField(
              controller: bodyController,
              decoration: const InputDecoration(
                label: Text("Body"),
                enabledBorder: OutlineInputBorder(),
              ),
            ),
            DropdownButton<String>(
              focusColor: Colors.white,
              value: _chosenValue,
              //elevation: 5,
              style: TextStyle(color: Colors.white),
              iconEnabledColor: Colors.black,
              items: Tag.map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(
                    value,
                    style: TextStyle(color: Colors.black),
                  ),
                );
              }).toList(),
              hint: const Text(
                "select a tag",
                style: TextStyle(
                    color: Colors.black,
                    fontSize: 14,
                    fontWeight: FontWeight.w500),
              ),
              onChanged: (String? value) {
                setState(() {
                  _chosenValue = value.toString();
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

This is the mock data class

import 'package:deep_pocket/models/data_feed.dart';
import 'package:flutter/material.dart';

class mockData with ChangeNotifier {
  final List<dataFeed> _data = [
    dataFeed(
      imgsrc: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
      name: "Priyam Srivastava",
      title: "How to change room ?",
      tag: 1,
      text:
          "I would like to know the process of changing my room cause I have not been able to study, and my roomate always plays music and drinks too much then shouts all night, please tell me how",
    ),
    dataFeed(
      imgsrc: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
      title: "Anyone intresed in playing BGMI?",
      name: "Part Agarwal",
      tag: 2,
      text:
          "So I have been looing for a squad for a long time and now i have finally decided that I am gonna buckle up and ask you all to join me",
    ),
    dataFeed(
      imgsrc: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
      title: "How to solve this question in O(n) complexity",
      name: "Preet Singh",
      tag: 3,
      text:
          "So I have been looing for a squad for a long time and now i have finally decided that I am gonna buckle up and ask you all to join me",
    ),
  ];
  List<dataFeed> get items {
    return [..._data];
  }

  void addPost(dataFeed newpost) {
    final newPost = dataFeed(
      imgsrc: newpost.imgsrc,
      name: newpost.name,
      title: newpost.title,
      text: newpost.text,
      tag: newpost.tag,
    );
    _data.insert(0, newPost);
    print(_data.length);
    notifyListeners();
  }
}


Datafield class

import 'package:provider/provider.dart';

import 'package:flutter/material.dart';

List<String> Tag = [
  'all',
  'Query',
  'Games',
  'Doubt',
  'Selling',
  'CabShare',
  'Announcement',
  'OpenDiscussion',
];

class dataFeed with ChangeNotifier {
  final String id = DateTime.now().toString();
  final String name;
  final String title;
  final String text;
  final String imgsrc;
  final DateTime date = DateTime.now();
  final int tag;

  dataFeed({
    required this.imgsrc,
    required this.name,
    required this.title,
    this.tag = 0,
    required this.text,
  });

CodePudding user response:

Firstly, wrap Scaffold with ChangeNotifierProvider<T> and change your floating action button onPressed function like this:

ChangeNotifierProvider<mockData>(
   create: (context) => mockData(),
   builder: (context, child){

     var posts = context.select((mockData m) => m.items);

     return Scaffold(
      body: SingleChildScrollView(
         ....
      ),
      floatingActionButton: FloatingActionButton(
      onPressed: () async {
        //Waiting for result
        var newData = await Navigator.pushNamed(context, userInput.route);
        if(newData != null){
          context.read<mockData>().addPost(newData);
        }
      },
      child: const Icon(Icons.add)),
   );
   }
);

Secondly, change your submitted function in userInput class like this:

void submitted(){
   ///....
   final newPost = dataFeed(
      imgsrc: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
      name: "Priyam ",
      title: titleCheck,
      text: bodyCheck,
      tag: tag,
    );
    titleController.dispose();
    bodyController.dispose();
    //Sending newPost to previous page via Navigator.
    Navigator.of(context).pop(newPost); //<- Attention
}

And change the below line in _feedScreenState for listening the list.

Instead

var posts = Provider.of<mockData>(context).items;

This:

var posts = context.watch<mockData>().items;
//or
var posts = context.select((mockData m) => m.items);

Or add a Selector widget for listening the list

Selector<mockData, List<dataFeed>>(
   selector: (_, m) => m.items,
   builder: (_, items, __) => ListView.builder(
      //...
      itemBuilder: (ctx, i) => postWidget(post: items[i])),
   )
)
  • Related