#flutter #dart #listview
#трепетать #дротик #просмотр списка
Вопрос:
Я разработал API, который действительно удаляет задания и отправляет свои данные в JSON обратно в Flutter. Однако любые новые поиски работы не обновляют Listview.builder, даже если метод _getJobs получает новые данные при каждом поиске из моей колбы. Метод FutureBuilder _jobSearch выполняется только один раз при перезапуске приложения, поэтому каждый раз выводятся одни и те же результаты и не выполняется снова для предстоящих поисков.
Вот мой код:
import 'package:flutter_job_portal/theme/colors.dart'; import 'package:flutter_job_portal/theme/images.dart'; import 'package:flutter_job_portal/ui/bottom_menu_bar.dart'; import 'package:flutter_job_portal/ui/job_detail_page.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'dart:async'; String job = ''; //user's response will be assigned to this variable final _formkey = GlobalKeylt;FormStategt;(); //key created to interact with the form class Job { final String title; final String company; final String location; final String salary; Job(this.title, this.company, this.location, this.salary); } class HomePage extends StatelessWidget { Futurelt;voidgt; _savingData() async { final validation = _formkey.currentState.validate(); if (!validation) { return; } _formkey.currentState.save(); } Futurelt;Listlt;Jobgt;gt; _getJobs() async { final url = 'http://127.0.0.1:5000/job'; final response = await http.post(Uri.parse(url), body: json.encode({'job': job})); final data = await http.get(Uri.parse(url)); final decoded = json.decode(data.body); Listlt;Jobgt; jobs = []; for (var i in decoded) { Job job = Job(i['Title'], i['Company'], i['Location'], i['Salary']); jobs.add(job); } return jobs; } const HomePage({Key key}) : super(key: key); Widget _appBar(BuildContext context) { return Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Row( children: [ CircleAvatar( backgroundImage: AssetImage(Images.user1), ), Spacer(), IconButton( icon: Icon(Icons.notifications_none_rounded), onPressed: () {}, ) ], ), ); } Widget _header(BuildContext context) { return Container( margin: EdgeInsets.symmetric(vertical: 12), padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Hello, Alex!", style: TextStyle( fontSize: 15, color: KColors.subtitle, fontWeight: FontWeight.w500, )), SizedBox( height: 6, ), Text("Swipe to find your future", style: TextStyle( fontSize: 20, color: KColors.title, fontWeight: FontWeight.bold)), SizedBox( height: 10, ), Row( children: [ Expanded( child: Container( height: 45, padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( color: KColors.lightGrey, borderRadius: BorderRadius.circular(10)), child: Form( key: _formkey, child: TextFormField( decoration: InputDecoration( hintText: 'Search job title or keywords', ), onSaved: (value) { job = value; //getting data from the user form and assigning it to job }, ), ), ), ), SizedBox( width: 16, ), Container( decoration: BoxDecoration( color: KColors.primary, borderRadius: BorderRadius.circular(10), ), height: 40, child: IconButton( color: KColors.primary, icon: Icon(Icons.search, color: Colors.white), onPressed: () async { _savingData(); _getJobs(); }, ), ) ], ) ], ), ); } Widget _recommendedSection(BuildContext context) { return Container( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10), margin: EdgeInsets.symmetric(vertical: 12), height: 200, width: MediaQuery.of(context).size.width, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Recommended", style: TextStyle(fontWeight: FontWeight.bold, color: KColors.title), ), SizedBox(height: 10), Expanded( child: ListView( scrollDirection: Axis.horizontal, children: [ _recommendedJob(context, company: "Google", img: Images.google, title: "Software Engineer", sub: "$125,000 Remote", isActive: true), _recommendedJob(context, company: "DropBox", img: Images.dropbox, title: "Research Assist", sub: "$45,000 Remote", isActive: false) ], ), ), ], ), ); } Widget _recommendedJob( BuildContext context, { String img, String company, String title, String sub, bool isActive = false, }) { return Padding( padding: const EdgeInsets.only(right: 10), child: GestureDetector( onTap: () { Navigator.push(context, JobDetailPage.getJobDetail()); }, child: AspectRatio( aspectRatio: 1.3, child: Container( decoration: BoxDecoration( color: isActive ? KColors.primary : Colors.white, borderRadius: BorderRadius.circular(7), ), padding: EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( height: 40, width: 40, padding: EdgeInsets.all(10), decoration: BoxDecoration( color: isActive ? Colors.white : KColors.lightGrey, borderRadius: BorderRadius.circular(7), ), child: Image.asset(img), ), SizedBox(height: 16), Text( company, style: TextStyle( fontSize: 12, color: isActive ? Colors.white38 : KColors.subtitle, ), ), SizedBox(height: 6), Text( title, style: TextStyle( fontSize: 14, color: isActive ? Colors.white : KColors.title, fontWeight: FontWeight.bold, ), ), SizedBox(height: 6), Text( sub, style: TextStyle( fontSize: 12, color: isActive ? Colors.white38 : KColors.subtitle, ), ), ], ), ), ), ), ); } FutureBuilderlt;Listlt;Jobgt;gt; _jobSearch() { return FutureBuilder( future: _getJobs(), builder: (context, snapshot) { if (snapshot.data == null) { return Container( child: Center( child: CircularProgressIndicator(), )); } else { return ListView.builder( physics: NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: snapshot.data.length, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data[index].company), subtitle: Text(snapshot.data[index].title), ); }, ); } }, ); } @override Widget build(BuildContext context) { return new Scaffold( backgroundColor: KColors.background, bottomNavigationBar: BottomMenuBar(), body: SafeArea( child: Container( width: MediaQuery.of(context).size.width, child: SingleChildScrollView( physics: ScrollPhysics(), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _appBar(context), _header(context), _recommendedSection(context), _jobSearch(), ], ), ), ), ), ); } }