Flutter Widgets → Flutter HTTP JSON ListView MasterDetail Images Text – Camposha

Flutter Widgets

Flutter Widgets

Flutter Widgets

Flutter HTTP JSON ListView MasterDetail Images Text

Flutter HTTP JSON ListView MasterDetail Images Text Tutorial

How to download JSON with images and Text via HTTP and bind to a custom listview with images and text. Then open a detail view of the listview when a listview item is clicked.

Demo

Here are demo for this project:

Flutter HTTP JSON Images text
Flutter HTTP JSON Images text

 

 

JSON data

Here’s the json data view. It’s available in this url https://raw.githubusercontent.com/Oclemy/SampleJSON/338d9585/spacecrafts.json.

 

JSON Data
JSON Data

Video Tutorial.

Here’s the corresponding video tutorial.

Video Tutorial

Here we have a video tutorial for this example.

ListView

One of the most commonly used widgets in any mobile app development framework is the ListView. It normally renders items in a linear manner and is always very flexible. A good way of getting a feel of a framework is to render items in a listview. Especially images and text.

That’s exactly what we do here. Then listen to listview itemClick events. Thus we show pass the clicked data to a new detail page/screen.

Here are several things you do here with a ListView

(a). How to Create a CustomListView

This ListView will be capable of rendering both images and text. It will render them in beautiful cardviews.

We will make the custom listview extend the StatelessWidget class:

class CustomListView extends StatelessWidget {..}

Inside the class we will have a method called createViewItem(). This method will define for us a single listview view item. Thata is a ListTile and its contents.

  Widget createViewItem(Spacecraft spacecraft, BuildContext context) {
    return new ListTile(
        title: new Card(
            ...

Our ListTiles will have CardViews. Those CardViews will have both image and texts.

(b). How to Listen to ListView itemClicks

Well you just use the onTap() callback.

        onTap: () {
          //..Open Second Page here.
        });

MaterialPageRoute

A MaterialPageRoute is a modal route that replaces the entire screen with a platform-adaptive transition.

(a). How to Create a MaterialPageRoute
We create one using the new constructor.

          var route = new MaterialPageRoute(
            builder: (BuildContext context) =>
                new SecondScreen(value: spacecraft),
          );

(b). How to Open a Second Page
We use the Navigator class. A Navigator is a widget that manages a set of child widgets with stack discipline.It allows us navigate pages. We invoke the push() method, passing in our MaterialPageRoute.

          Navigator.of(context).push(route);

http

http is the package in flutter that allows us perform our HTTP Requests. In this case we want to perform a HTTP GET request. This means we want to download some data.

First we need to import http package:

import 'package:http/http.dart' show get;

Then we need a jsonEndpoint, basically our url string. Then we invoke the get which is equivalent to http.get:

  final jsonEndpoint =
      "https://raw.githubusercontent.com/Oclemy/SampleJSON/338d9585/spacecrafts.json";

  final response = await get(jsonEndpoint);

We will check if our response is HTTP.OK which universally equals 200 response code.

We are making this operation asynchronous. We will be returning a Future<T> object. That means this is a delayed computation and our result is not going to be immediately available. Instead it is avaialable in the future, once our download is complete.

Future<List<Spacecraft>> downloadJSON() async {
  final jsonEndpoint =
      "https://raw.githubusercontent.com/Oclemy/SampleJSON/338d9585/spacecrafts.json";

  final response = await get(jsonEndpoint);

  if (response.statusCode == 200) {
    List spacecrafts = json.decode(response.body);
    return spacecrafts
        .map((spacecraft) => new Spacecraft.fromJson(spacecraft))
        .toList();
  } else
    throw Exception('We were not able to successfully download the json data.');
}

(a). main.dart

Here’s the complete code.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'dart:convert';
class Spacecraft {
final String id;
final String name, imageUrl, propellant;
Spacecraft({
this.id,
this.name,
this.imageUrl,
this.propellant,
});
factory Spacecraft.fromJson(Map<String, dynamic> jsonData) {
return Spacecraft(
id: jsonData['id'],
name: jsonData['name'],
propellant: jsonData['propellant'],
imageUrl: jsonData['imageurl'],
);
}
}
class CustomListView extends StatelessWidget {
final List<Spacecraft> spacecrafts;
CustomListView(this.spacecrafts);
Widget build(context) {
return ListView.builder(
itemCount: spacecrafts.length,
itemBuilder: (context, int currentIndex) {
return createViewItem(spacecrafts[currentIndex], context);
},
);
}
Widget createViewItem(Spacecraft spacecraft, BuildContext context) {
return new ListTile(
title: new Card(
elevation: 5.0,
child: new Container(
decoration: BoxDecoration(border: Border.all(color: Colors.orange)),
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
child: Image.network(spacecraft.imageUrl),
padding: EdgeInsets.only(bottom: 8.0),
),
Row(children: <Widget>[
Padding(
child: Text(
spacecraft.name,
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
Text(" | "),
Padding(
child: Text(
spacecraft.propellant,
style: new TextStyle(fontStyle: FontStyle.italic),
textAlign: TextAlign.right,
),
padding: EdgeInsets.all(1.0)),
]),
],
),
),
),
onTap: () {
//We start by creating a Page Route.
//A MaterialPageRoute is a modal route that replaces the entire
//screen with a platform-adaptive transition.
var route = new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondScreen(value: spacecraft),
);
//A Navigator is a widget that manages a set of child widgets with
//stack discipline.It allows us navigate pages.
Navigator.of(context).push(route);
});
}
}
//Future is n object representing a delayed computation.
Future<List<Spacecraft>> downloadJSON() async {
final jsonEndpoint =
"https://raw.githubusercontent.com/Oclemy/SampleJSON/338d9585/spacecrafts.json";
final response = await get(jsonEndpoint);
if (response.statusCode == 200) {
List spacecrafts = json.decode(response.body);
return spacecrafts
.map((spacecraft) => new Spacecraft.fromJson(spacecraft))
.toList();
} else
throw Exception('We were not able to successfully download the json data.');
}
class SecondScreen extends StatefulWidget {
final Spacecraft value;
SecondScreen({Key key, this.value}) : super(key: key);
@override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Detail Page')),
body: new Container(
child: new Center(
child: Column(
children: <Widget>[
Padding(
child: new Text(
'SPACECRAFT DETAILS',
style: new TextStyle(fontWeight: FontWeight.bold,fontSize: 20.0),
textAlign: TextAlign.center,
),
padding: EdgeInsets.only(bottom: 20.0),
),
Padding(
//`widget` is the current configuration. A State object's configuration
//is the corresponding StatefulWidget instance.
child: Image.network( '${widget.value.imageUrl}'),
padding: EdgeInsets.only(bottom: 8.0),
),
Padding(
child: new Text(
'NAME : ${widget.value.name}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(20.0),
),
Padding(
child: new Text(
'PROPELLANT : ${widget.value.propellant}',
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(20.0),
)
],   ),
),
),
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new Scaffold(
appBar: new AppBar(title: const Text('JSON Images Text')),
body: new Center(
//FutureBuilder is a widget that builds itself based on the latest snapshot
// of interaction with a Future.
child: new FutureBuilder<List<Spacecraft>>(
future: downloadJSON(),
//we pass a BuildContext and an AsyncSnapshot object which is an
//Immutable representation of the most recent interaction with
//an asynchronous computation.
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Spacecraft> spacecrafts = snapshot.data;
return new CustomListView(spacecrafts);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
//return  a circular progress indicator.
return new CircularProgressIndicator();
},
),
),
),
);
}
}
void main() {
runApp(MyApp());
}

(b). pubspec.yaml

We are not using any third party library.

name: json_images
description: A new Flutter project.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true

How to Download and Run.

We are not using any third party library hence all you need to do is copy the main.dart file into your project. The JSON is luckily available online so you just run the app and it will work.

Leave a Reply

Your email address will not be published. Required fields are marked *

Rating

Not enough ratings to display
Join Us
X