RSS / XML parsing - html

Am stuck trying to parse and display rss feed data. How can I easily get these links to all work? What library should be used. Thanks!
Currently using https://pub.dev/packages/webfeed
DART /Flutter mobile application
Cannot seem to parse and render links below:
https://academic.oup.com/rss/site_5267/3133.xml (Returns 405)
https://journals.lww.com/co-anesthesiology/_layouts/15/OAKS.Journals/feed.aspx?FeedType=MostPopularArticles (won't load or import xml)
Have this link working ok:
http://anesthesiology.pubs.asahq.org/rss/site_157/173.xml
import 'dart:io';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:wcm_anes/common/circularIndicator.dart';
import 'package:wcm_anes/customIcons/custom_icons_icons.dart';
import 'package:wcm_anes/styles/colorAsset.dart';
import 'package:wcm_anes/styles/stringAssets.dart';
import 'package:wcm_anes/styles/textStyles.dart';
import 'package:webfeed/webfeed.dart';
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
class RssUrlListScreen extends StatefulWidget {
String screenName;
String feedUrl;
String categoryId;
RssUrlListScreen({this.screenName,this.feedUrl,this.categoryId});
#override
_RssUrlListScreenState createState() => _RssUrlListScreenState();
}
class _RssUrlListScreenState extends State<RssUrlListScreen> {
static const String loadingMessage = 'Loading Feed...';
static const String feedLoadErrorMessage = 'Error Loading Feed.';
static const String feedOpenErrorMessage = 'Error Opening Feed.';
String _title;
RssFeed feed;
bool isLoading = false;
updateTitle(title) {
setState(() {
_title = title;
});
}
updateFeed(feed) {
setState(() {
feed = feed;
});
}
Future<void> openFeed(String url) async {
if (await canLaunch(url)) {
await launch(
url,
forceSafariVC: true,
forceWebView: false,
);
return;
}
updateTitle(feedOpenErrorMessage);
}
// Method to load the RSS data.
load() async {
updateTitle(loadingMessage);
loadFeed().then((result) {
if (result == null || result.toString().isEmpty) {
// Notify user of error.
updateTitle(feedLoadErrorMessage);
return;
}
setState(() {
feed = result;
isLoading = false;
});
});
}
// Method to get the RSS data
Future<RssFeed> loadFeed() async {
try {
final client = http.Client();
final response = await client.get(widget.feedUrl);
print("responssssurl>> ${response.body}");
return RssFeed.parse(utf8.decode(response.bodyBytes));
} catch (e) {
print("execption>> $e");
// handle any exceptions here
}
return null;
}
#override
void initState() {
updateTitle(widget.screenName);
isLoading = true;
load();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
brightness: Platform.isIOS?Brightness.light:Brightness.dark,
title:feed != null?Text(feed.title,style:headerTextStyle):Container(),
leading: IconButton(
onPressed: (){
Navigator.pop(context);
},
icon:Icon(Icons.arrow_back_ios,color: ColorAsset.tabColorGray,size:20.0,)),
backgroundColor: Colors.white,
elevation: 0.0,
titleSpacing: 0.0,
centerTitle: true,
),
body: Stack(
children: <Widget>[
feed != null?
feed.items.length>0?ListView.builder(
physics: new ClampingScrollPhysics(),
itemCount: feed.items.length,
itemBuilder: (BuildContext context, int index){
final feedItems = feed.items[index];
print("rssTitle>>> ${feedItems.title}");
return Container(
margin: EdgeInsets.only(left:13.0,right:13.0),
child: Center(
child: Card(
elevation: 1.0,
child: ListTile(
onTap: (){
openFeed(feedItems.link);
},
title: Text(feedItems.title,style:listTextStyle),
subtitle: Text(feedItems.pubDate,style: subCategoroyTextStyle,),
contentPadding: EdgeInsets.all(5.0),
trailing: Padding(
padding: EdgeInsets.only(top:15.0,bottom:15.0),
child: Icon(CustomIcons.next,size:20.0,),
)
),
),
),
);
}
):Container(
margin: EdgeInsets.only(top:(MediaQuery.of(context).size.height/2)-110),
child: Text(StringAssets.noData,
style: listTextStyle,
),
)
:Container(),
Visibility(
visible: isLoading,
child: Container(
//margin: EdgeInsets.only(top:(MediaQuery.of(context).size.height/2)-110),
child: Center(
child: CircularIndiacator()
),
),
)
],
),
);
}
}

Related

Error in searching data using listview in flutter

I've tried this code for searching jobs in listview but the data is not shown in listview. I think JSON is not parsing properly for Jobs data.
Here is the code of the model:
import 'package:flutter/material.dart';
class JobItem {
final String title;
final String description;
JobItem(
{
required this.title,
required this.description,
});
factory JobItem.fromJson(Map<String, dynamic> json) {
return JobItem(
title: json['title'] as String,
description: json['description'] as String,
);
}
}
Here I've written code for the main file to search data from the listview.
List<JobItem> users = [];
List<JobItem> filteredUsers = [];
static String url = 'https://hospitality92.com/api/jobsbycategory/All';
static Future<List<JobItem>> getJobsData() async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
List<JobItem> list = parseAgents(response.body);
return list;
} else {
throw Exception('Error');
}
} catch (e) {
throw Exception(e.toString());
}
}
static List<JobItem> parseAgents(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<JobItem>((json) => JobItem.fromJson(json)).toList();
}
#override
void initState() {
super.initState();
getJobsData().then((usersFromServer) {
setState(() {
users = usersFromServer;
filteredUsers = users;
});
});
}```
Try below code your problem has been solved :
//declare packages
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
class Jobs extends StatefulWidget {
Jobs() : super();
#override
JobsState createState() => JobsState();
}
class Debouncer {
final int milliseconds;
VoidCallback action;
Timer _timer;
Debouncer({this.milliseconds});
run(VoidCallback action) {
if (null != _timer) {
_timer.cancel();
}
_timer = Timer(Duration(milliseconds: milliseconds), action);
}
}
class JobsState extends State<Jobs> {
final _debouncer = Debouncer(milliseconds: 500);
List<Subject> subjects = [];
List<Subject> filteredSubjects = [];
//API call for All Subject List
static String url = 'https://hospitality92.com/api/jobsbycategory/All';
static Future<List<Subject>> getAllSubjectsList() async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
print(response.body);
List<Subject> list = parseAgents(response.body);
return list;
} else {
throw Exception('Error');
}
} catch (e) {
throw Exception(e.toString());
}
}
static List<Subject> parseAgents(String responseBody) {
final parsed =
json.decode(responseBody)['jobs'].cast<Map<String, dynamic>>();
return parsed.map<Subject>((json) => Subject.fromJson(json)).toList();
}
#override
void initState() {
super.initState();
getAllSubjectsList().then((subjectFromServer) {
setState(() {
subjects = subjectFromServer;
filteredSubjects = subjects;
});
});
}
//Main Widget
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'All Subjects',
style: TextStyle(fontSize: 25),
),
),
body: Column(
children: <Widget>[
//Search Bar to List of typed Subject
Container(
padding: EdgeInsets.all(15),
child: TextField(
textInputAction: TextInputAction.search,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
borderSide: BorderSide(
color: Colors.grey,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
borderSide: BorderSide(
color: Colors.blue,
),
),
suffixIcon: InkWell(
child: Icon(Icons.search),
),
contentPadding: EdgeInsets.all(15.0),
hintText: 'Search ',
),
onChanged: (string) {
_debouncer.run(() {
setState(() {
filteredSubjects = subjects
.where((u) => (u.title
.toLowerCase()
.contains(string.toLowerCase())))
.toList();
});
});
},
),
),
//Lists of Subjects
Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
padding: EdgeInsets.only(top: 20, left: 20, right: 20),
itemCount: filteredSubjects.length,
itemBuilder: (BuildContext context, int index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(
color: Colors.grey[300],
),
),
child: Padding(
padding: EdgeInsets.all(5.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: Text(
filteredSubjects[index].skills,
),
title: Text(
filteredSubjects[index].title,
style: TextStyle(fontSize: 16),
),
trailing: Text(filteredSubjects[index].position.toString()),
)
],
),
),
);
},
),
),
],
),
);
}
}
//Declare Subject class for json data or parameters of json string/data
//Class For Subject
class Subject {
String title;
int id;
String skills;
String position;
Subject({
this.id,
this.title,
this.skills,
this.position,
});
factory Subject.fromJson(Map<String, dynamic> json) {
return Subject(
title: json['title'] as String,
id: json['id'],
skills: json['skills'],
position: json['positions']);
}
}
Your screen before search:
Your Screen after search :
U have a little mistake in parsing. I added response.body['jobs'].
static Future<List<JobItem>> getJobsData() async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
List<JobItem> list = parseAgents(Map<String, dynamic>.from(jsonDecode(response.body))['jobs']);
return list;
} else {
throw Exception('Error');
}
} catch (e) {
throw Exception(e.toString());
} }

Flutter. Add a json.decode value to a String that can be used in the UI

Maybe this is a simple question, but I can't find the answer to it.
My app has 2 screens. 1st has a single button
onPressed: () {
fetchCurrentTitle();
Navigator.push(context,
MaterialPageRoute(builder: (context) => Screen2Widget()));
},
fetchCurrentTitle() method fetches data from json and decodes it.
I can see the return using:
final streamFullTitle = json.decode(response.body)['data'][0]['title'];
print(streamFullTitle);
I get the desired response of the current title in the console.
In the 2nd screen I have a hardcoded List. Where items have these values:
class List {
String id;
String streamer;
String logoUrl;
String title;
}
The first three attribute in List class dont need to change so they are hardcoded. I just need to assign the title value fromfetchCurrentTitle() to the String title. in class List.
Look of one of my list items
My fetchCurrentTitle() works as intended
Future<String> fetchCurrentTitle() async {
http.Response response = await http.get(...
I want the user to push the button on the first screen to go to the second screen and show a spinner with title "looking for title" and then get the new title instead of waiting fetchCurrentTitle() to complete only entering the second screen.
Thank you in advance.
You can try to run your fetchCurrentTitle() in the second screen on
void initState() {
super.initState();
fetchCurrentTitle()
/// show or set visibility for loading spinner
}
After you get the title value, you can simply assign new title by
List existingList = new List(id,streamer,logoUrl,title);
existingList.id = titleValueFromApi
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sample_project_for_api/Employee.dart';
void main() => runApp(MaterialApp(
title: "App",
home: MyApp(),
));
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('home page'),
),
body: Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: RaisedButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => SecondScreen()));
},
child: const Text('First Page')),
)),
);
}
}
class SecondScreen extends StatefulWidget {
#override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
bool _isLoading = false;
Employee sampleData;
#override
void initState() {
super.initState();
getYouData();
}
Future<String> loadPersonFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
getYouData() async {
setState(() {
_isLoading = true;
});
String jsonString = await loadPersonFromAssets();
final data = employeeFromJson(jsonString);
sampleData = data;
// this is where you get the data from the network
Future.delayed(const Duration(seconds: 5), () {
// this is sample delay for you to know the delay.
// you can say this is loading your data
setState(() {
_isLoading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
child: _isLoading
//here give your message getting the title
? CircularProgressIndicator()
: Card(
child: Column(
children: <Widget>[
Text('your 1st hardcoded text'),
Text('your 2st hardcoded text'),
Text('your 3st hardcoded text'),
Text(
'This is your dynamic data after fetching :${sampleData.employeeName}')
],
),
),
),
),
),
);
}
}
check out this example you will give you an idea of what to do
1) going from one page to another page
2) loading you data , while that showing the spinner
3) on fetching the data update the UI.
let me know about this.
Thanks.
Try this,
import 'dart:convert';
import "package:flutter/material.dart";
import 'package:http/http.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Page1(),
);
}
}
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 1")),
body: Center(
child: RaisedButton(
child: Text("Goto Page2"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Page2(),
),
);
},
),
),
);
}
}
class Page2 extends StatefulWidget {
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
Future<void> _initLoader;
String _title;
#override
void initState() {
_initLoader = _loadInitData();
super.initState();
}
Future<void> _loadInitData() async {
await Future.delayed(Duration(seconds: 2));
//_title = await fetchCurrentTitle();
_title = "This is the Loaded Title";
}
Future<String> fetchCurrentTitle() async {
Response response = await get("...");
return json.decode(response.body)['data'][0]['title'];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 2")),
body: FutureBuilder(
future: _initLoader,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
CircularProgressIndicator(),
const SizedBox(height: 8.0),
Text("Looking for Title"),
],
),
);
else if (snapshot.hasError)
return Center(
child: Text("Error: ${snapshot.error}"),
);
else
return Center(
child: Text("$_title"),
);
},
),
);
}
}

Flutter: Loading json data within second page Flutter Class timing out without error

I've generated a listView from the Pokemon API of a list of Pokemon, I then have onTap events to trigger a new page/class, where I'm passing the name and URL from the API to the new secondPage Class/Screen.
I need to make a second request in this new page because the API Url needs to change to grab specific details but my request seems to be timing out..
Here is my code: If loaded into a new project the first screen should function fine, loading a bunch of Pokemon and their API specific URLs into a listView.
I can successfully pass the name and URL onto the second screen because they do appear in the Appbar.
However when loading the new json data it seems to be timing out without any error.
Does anyone have any advice for a newbie trying to get his footing?
import 'dart:async';
import 'dart:convert';
import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController editingController = TextEditingController();
String url = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
List data;
Future<String> makeRequest() async {
var response = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var extractData = json.decode(response.body);
data = extractData["results"];
});
}
#override
void initState() {
this.makeRequest();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Pokemon List'),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: new TextField(
onChanged: (value) {
},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
contentPadding: const EdgeInsets.all(10.0),
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(6.0))
),
),
),
),
Expanded(
child: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(StringUtils.capitalize(data[i]["name"])),
subtitle: new Text(data[i]["url"]),
// leading: new CircleAvatar(
// backgroundImage:
// new NetworkImage(data[i]["picture"]["thumbnail"]),
// ),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondPage(data[i])
)
);
},
);
}
),
),
],
),
),
);
}
}
// Class for getting Specific Details on SecondPage
class Post {
final String name;
final int weight;
Post({this.name, this.weight});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
name: json['name'],
weight: json['weight'],
);
}
}
// New Request for Specific Details
class SecondPage extends StatelessWidget {
SecondPage(this.data);
final data;
Future<Post> fetchPost() async {
final response =
await http.get('https://pokeapi.co/api/v2/pokemon/' + data["name"]);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
Future<Post> post;
#override
void initState() {
fetchPost();
post = fetchPost();
}
#override
Widget build(BuildContext context) =>
new Scaffold(
appBar: new AppBar(
title: new Text(data["name"] + ' - ' + data["url"])),
body: new Center(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.all(30.0),
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
Text(snapshot.data.name);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
],
),
)
);
}
Man, I rewrite your code as I like
import 'dart:async';
import 'dart:convert';
//import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController editingController = TextEditingController();
String url = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
List data;
Future<String> makeRequest() async {
var response = await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var extractData = json.decode(response.body);
data = extractData["results"];
});
}
#override
void initState() {
super.initState();
makeRequest();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pokemon List'),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: TextField(
onChanged: (value) {},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
contentPadding: const EdgeInsets.all(10.0),
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(6.0))),
),
),
),
Expanded(
child: ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return ListTile(
title: Text(data[i]["name"].toString().toUpperCase()),
subtitle: Text(data[i]["url"]),
// leading: CircleAvatar(
// backgroundImage:
// NetworkImage(data[i]["picture"]["thumbnail"]),
// ),
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (BuildContext context) => SecondPage(data[i])));
},
);
}),
),
],
),
),
);
}
}
class SecondPage extends StatefulWidget {
Map data;
SecondPage(this.data);
_SecondState createState() => _SecondState();
}
class _SecondState extends State<SecondPage> {
#override
void initState() {
super.initState();
_fetchPost();
}
Map post;
bool isLoad = true;
_fetchPost() async {
setState(() {
isLoad = true;
});
var url = widget.data["url"];
debugPrint(url);
final response = await http.get(url);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
post = json.decode(response.body.toString());
setState(() {
isLoad = false;
});
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.data["name"] + ' - ' + widget.data["url"])),
body: _buildPokemon(context),
);
}
Widget _buildPokemon(BuildContext context) {
if (isLoad) return Center(child: CircularProgressIndicator());
return Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(post['name']),
Text(post['weight'].toString()),
Text(post['height'].toString()),
Image.network(post['sprites']['front_default'])
],
),
);
}
}

How to setState http url?

I want to create a news app and I've used newsapi.org as well but The
problem is actually that I want to make something like search feature in my
app and my idea is very simple.
I've created a TextField in the AppBar and my idea is to take the input from
user and setState with the new url of user input.
My Code:
import 'package:flutter/material.dart';
import 'package:newly/services/networking.dart';
import 'package:newly/widgets/article.dart';
class NewsScreen extends StatefulWidget {
#override
_NewsScreenState createState() => _NewsScreenState();
}
class _NewsScreenState extends State<NewsScreen> {
List<Article> articles = [];
String topic = 'google';
var newsData;
Future getNews(String topic) async {
NetworkHelper networkHelper = NetworkHelper(
url:
'https://newsapi.org/v2/everything?q=$topic&from=2019-11-04&to=2019-11-04&sortBy=popularity&apiKey=392495172bab4b3885ae93760df54b91',
);
newsData = await networkHelper.getData();
for (int i = 0; i < newsData['articles'].length; i++) {
var title = newsData['articles'][i]['title'];
var urlToImage = newsData['articles'][i]['urlToImage'];
var content = newsData['articles'][i]['content'];
var author = newsData['articles'][i]['author'];
var url = newsData['articles'][i]['url'];
setState(() {
articles.add(
Article(
author: author,
content: content,
title: title,
url: url,
urlToImage: urlToImage,
),
);
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
centerTitle: true,
title: TextField(
textInputAction: TextInputAction.search,
onChanged: (String text) async {
setState(() {
topic = text;
});
await getNews(topic);
print(topic);
},
onSubmitted: (String text) async {
setState(() {
topic = text;
});
print(topic);
await getNews(topic);
},
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () async {
await getNews(topic);
print(topic);
},
icon: Icon(
Icons.search,
),
),
hintText: 'Search',
filled: true,
fillColor: Colors.white,
),
),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: FutureBuilder(
future: getNews(topic),
builder: (context, snapshot) {
return ListView.builder(
itemCount: newsData['articles'] == null
? 0
: newsData['articles'].length,
itemBuilder: (BuildContext ctxt, int index) {
return Article(
author: articles[index].author,
content: articles[index].content,
title: articles[index].title,
url: articles[index].url,
urlToImage: articles[index].urlToImage,
);
},
);
},
),
),
),
);
}
}
Network Helper :
import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper {
NetworkHelper({this.url});
final String url;
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
return json.decode(data);
} else {
print('something wrong');
print(response.statusCode);
}
}
}

Flutter, fetching specfic image from website

I'm learning flutter and want to fetch various images which are the thumbnail of the cartoon. I used HTTP library and fetched response data.
But, how can I extract that image?
Website: https://comic.naver.com/webtoon/weekdayList.nhn?week=
Future<http.Response> _getData() async {
return await http.get('https://comic.naver.com/webtoon/weekdayList.nhn?week=');
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
),
body: Center(
child: RaisedButton(
child: Text("Fetching"),
onPressed: (){
_getData().then((response){
//dom.Document document = parser.parse(response.body);
print(response.body);
}).catchError((e) => print(e));
},
),
),
);
}
What I want to do is below.
Fetching web page as HTML code
Find image url of each cartoon
Fetch that image
Here you have a basic example, after you press the top-right button, you will get the images in a ListView:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:html/parser.dart' as parser;
import 'package:html/dom.dart' as dom;
...create your StatefulWidget
class ParsingWidgetState extends State<ParsingWidget> {
List<String> list = List();
void _getData() async {
final response =
await http.get('https://comic.naver.com/webtoon/weekdayList.nhn?week=');
dom.Document document = parser.parse(response.body);
final elements = document.getElementsByClassName('thumb');
setState(() {
list = elements
.map((element) =>
element.getElementsByTagName("img")[0].attributes['src'])
.toList();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
_getData();
},
),
],
),
body: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return Image.network(
list[index],
height: 200.0,
);
},
));
}
}
Try using FutureBuilder instead setState, this is just a working sample.
More info:
https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html
https://flutter-academy.com/async-in-flutter-futurebuilder/