Home > Enterprise >  flutter future builder keeps loading one-to-many relationship
flutter future builder keeps loading one-to-many relationship

Time:05-04

im tring to view tasks on alone screen from data using rest api dart django with project_id its one-to-many relationship project has many tasks so i want to dispay the tasks when i click on project widget using future builder

Edit :i found the problem check my answer below here is usage of future builder and task list

import 'package:flutter/material.dart';
import 'package:project/model/task_model.dart';
import 'package:project/project_dtetailForTest.dart';
import 'package:provider/provider.dart';
import 'new_project.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
class  TaskById extends StatefulWidget {
  //const TaskById({ Key? key }) : super(key: key);
  final int project_id;
  //final Task task =Task();
  TaskById({required this.project_id}):super();
  @override
  State<TaskById> createState() => _TaskByIdState();
}

class _TaskByIdState extends State<TaskById> {

  @override
  Widget build(BuildContext context) {
    final taskP= Provider.of<TaskProvider>(context);
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        elevation: 0,
        bottom: PreferredSize(
        child: Container(
         color: const Color(0xff94adb4),
         height: 2,
         width: 320,
      ),
      preferredSize: const Size.fromHeight(4.0)),
        centerTitle: true,
        backgroundColor:const Color(0xff076792),
        title: const Text(
          'Project1',
           style: TextStyle(color: Colors.white,
             fontSize: 35,
             fontWeight:FontWeight.w700,
             shadows: [
               Shadow(
                  color: Color(0xa6A2B6D4),
                  blurRadius:20),
              ] ),
        ),
        leading: IconButton(
          onPressed: () {
            Navigator.pop(context);
          },
          icon: const Icon(
            Icons.arrow_back,
            size: 44,
          ),
        ),
       actions:[Container(padding: const EdgeInsets.fromLTRB(0, 0, 6, 3),
         child: IconButton(
            color:Colors.white ,
            icon: const Icon(
              Icons.search,
              size: 44,
            ),
            onPressed: () {},
          ),
       ),] 
      ),
      //TaskProvider(){
  //   this.fetchTask();
  // }
      body: FutureBuilder(
        future: TaskProvider().fetchTask(widget.project_id),
        builder: (context, snapshot){
          if (snapshot.hasError) print(snapshot.error);
          return snapshot.hasData && snapshot is List<Task>
          ?TaskList(task:snapshot.data as List<Task>)
          :Center(child: CircularProgressIndicator());
        }),

    //    FutureProvider(
    //     create: (context) => TaskProvider().fetchTask() ,
    //     initialData:  [CircularProgressIndicator()],
    //     child:Center(child: Consumer<Task>( 
    //       builder: (context, task, widget) {
    //         return (taskP !=null) ? Column(
    //     children: [
    //       Row(
    //         children:  const [
    //           Padding(padding: EdgeInsets.all(7),
    //            child: Padding(
    //             padding: EdgeInsets.fromLTRB(24,10,10,8),
    //             child: Text('Project1',
    //             style: TextStyle(
    //               color: Color(0xff076792),
    //               fontSize: 40,
    //               fontWeight: FontWeight.w600
    //             ),
    //             ),
    //            ),
    //           ),              
    //         ],
    //       ),
    //       // dynamic list
    //      Expanded(
    //        child: ListView.builder(
    //        itemCount: taskP.task.length ,
    //        itemBuilder: (BuildContext context, int index) {
    //          return  Padding(
    //         padding:  const EdgeInsets.fromLTRB(28, 12, 28, 0),
    //         child: GestureDetector(
    //           onTap: () {
               
    //             Navigator.push(context, MaterialPageRoute(builder: (context) => projectDetails()));
    //           },
    //            child: Card(child:Container(padding: const EdgeInsets.fromLTRB(18,8,9,4),
    //             width: 100,
    //             height: 100,
    //              decoration: BoxDecoration(
    //              borderRadius: BorderRadius.circular(19.0),
    //               color: const Color(0xff076792),
    //               boxShadow:  const [
    //               BoxShadow(color: Colors.black, spreadRadius: 1),
    //               BoxShadow(color: Color(0xa6A2B6D4),               
    //                  offset: Offset(7,5),
    //                  blurRadius:20),
    //               ],
    //               ),
    //             child: Column(children: [
    //               Row(mainAxisAlignment: MainAxisAlignment.start,
    //                 children: [
    //                   Text('Starting ' taskP.task[index].start.toString(),style:
    //                     const TextStyle(color: Color.fromARGB(255, 133, 186, 202),fontSize: 18,),
    //                    ),
    //                 ],
    //               ),
    //               const Spacer(),
    //               Row(mainAxisAlignment: MainAxisAlignment.center,
    //                 children: [
    //                   Text(taskP.task[index].title??'',style:
    //                    const TextStyle(color: Colors.white,fontSize: 34,)),
    //                 ],
    //               ),
    //               const Spacer(),
    //               Row(mainAxisAlignment: MainAxisAlignment.end,
    //                 children: [
    //                   Text('Ending ' taskP.task[index].end.toString(),style:
    //                    const TextStyle(color: Color.fromARGB(255, 133, 186, 202),
    //                    fontSize: 18,
    //                    )),
    //                 ],
    //               ),
    //             ]),
    //           ),),
    //         ),
    //       );
    //        }),
    //      )
    //      ],
    //   )
    //         : CircularProgressIndicator();
    //       },
    //     ) ,
        
    //     ) 
    // //         widget.project_id),
          
    // //       builder: (context, snapshot){
    // //         if (snapshot.hasError) print(snapshot.error);
    // //         return snapshot.hasData
    // //             ? TaskList(taskP: snapshot.data)
    // //             : Center(child: CircularProgressIndicator());
    // //       }),
    // )
    ); 
  }
}
class TaskList extends StatelessWidget {

  final List <Task> task;
  TaskList({Key? key, required this.task}) : super(key: key);
  @override
  Widget build(BuildContext context) {
      final taskP= Provider.of<TaskProvider>(context );
    // TODO: implement build
    return Column(
        children: [
          Row(
            children:  const [
              Padding(padding: EdgeInsets.all(7),
               child: Padding(
                padding: EdgeInsets.fromLTRB(24,10,10,8),
                child: Text('Project1',
                style: TextStyle(
                  color: Color(0xff076792),
                  fontSize: 40,
                  fontWeight: FontWeight.w600
                ),
                ),
               ),
              ),              
            ],
          ),
          // dynamic list
         Expanded(
           child: ListView.builder(
           itemCount: taskP.task.length ,
           itemBuilder: (BuildContext context, int index) {
             return  Padding(
            padding:  const EdgeInsets.fromLTRB(28, 12, 28, 0),
            child: GestureDetector(
              onTap: () {
               
                Navigator.push(context, MaterialPageRoute(builder: (context) => projectDetails()));
              },
               child: Card(child:Container(padding: const EdgeInsets.fromLTRB(18,8,9,4),
                width: 100,
                height: 100,
                 decoration: BoxDecoration(
                 borderRadius: BorderRadius.circular(19.0),
                  color: const Color(0xff076792),
                  boxShadow:  const [
                  BoxShadow(color: Colors.black, spreadRadius: 1),
                  BoxShadow(color: Color(0xa6A2B6D4),               
                     offset: Offset(7,5),
                     blurRadius:20),
                  ],
                  ),
                child: Column(children: [
                  Row(mainAxisAlignment: MainAxisAlignment.start,
                    children: [
                      Text('Starting ' taskP.task[index].start.toString(),style:
                        const TextStyle(color: Color.fromARGB(255, 133, 186, 202),fontSize: 18,),
                       ),
                    ],
                  ),
                  const Spacer(),
                  Row(mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(taskP.task[index].title??'',style:
                       const TextStyle(color: Colors.white,fontSize: 34,)),
                    ],
                  ),
                  const Spacer(),
                  Row(mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      Text('Ending ' taskP.task[index].end.toString(),style:
                       const TextStyle(color: Color.fromARGB(255, 133, 186, 202),
                       fontSize: 18,
                       )),
                    ],
                  ),
                ]),
              ),),
            ),
          );
           }),
         )
         ],
      );
  }
}

here the api and model of task

// To parse this JSON data, do
//
//     final task = taskFromJson(jsonString);
import 'dart:collection';
import 'dart:core';
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

//List<Task> taskFromJson(String str) => List<Task>.from(json.decode(str).map((x) => Task.fromJson(x)));

//String taskToJson(List<Task> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Task {
  String? url;
  int? id;
  String? owner;
  String? project;
  String? title;
  DateTime? start;
  DateTime? end;
  String? desc;
  int? project_id;

  Task(
      {this.url,
      this.id,
      this.owner,
      this.project,
      this.title,
      this.start,
      this.end,
      this.desc,
      this.project_id});

  
  factory Task.fromJson(Map<String, dynamic> json) => Task(
    url :json["url"],
    id: json["id"],
    owner: json["owner"],
    project: json["project"],
    title: json["title"],
    start: DateTime.parse(json["start"]),
    end: DateTime.parse(json["end"]),
    desc: json["desc"],
    project_id: json["project_id"],
    
    
  );

  Map<String, dynamic> toJson() => {
    "url": url,
    "id": id,
    "owner": owner,
    "project": project, 
    "title": title,
    "start": start?.toIso8601String(),
    "end": end?.toIso8601String(),
    "desc": desc,
    "project_id": project_id,
  };
}
class TaskProvider with ChangeNotifier{
  TaskProvider(){
    this.fetchTask();
  }


  List<Task> _task = [];
  List<Task> get task {
    return [..._task];
  }

    void addTask(Task task) async {
    final response = await http.post(Uri.parse('http://mostafahamed.pythonanywhere.com/project/task'),
        headers: {"Content-Type": "application/json"}, body: json.encode(task));
    if (response.statusCode == 201) {
      task.id = json.decode(response.body)['id'];
      _task.add(task);
      notifyListeners();
      print('suceeed add ed task');
      print(response.body);
    }else{
      print(response.body);
       print('failed add ed task');
    }
  }

  void deleteTask(Task task) async {
    final response =
        await http.delete(Uri.parse('http://mostafahamed.pythonanywhere.com/project/task${task.id}/'));
    if (response.statusCode == 204) {
      _task.remove(task);
      notifyListeners();
    }
  }


     Future<List<Task>> fetchTask([project_id]) async{
     final response = await http
      .get(Uri.parse('http://mostafahamed.pythonanywhere.com/tasks/?format=json'));
    if (response.statusCode==200){
      var data = json.decode(response.body)as List;
      _task=data.map<Task>((json) => Task.fromJson(json)).toList();
      
      
      notifyListeners();
       print('sucess view task list');
       print(response.body);
       return _task;
    }
   else {
     print(response.body);
     print(response.statusCode);
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load tasks');
    
  }
  }
}

when i click on project wiget the screen keeps loading

CodePudding user response:

I removed a condition && snapshot is List from future builder and it works perfectly but make sure to prevent the use of future builder if you have changeable values as future builder fetch data once I'm right now working to convert future builder into stream builder

if u have the same problem make sure all the types are the same good luck to you all : )

  • Related