Build Android Application using Flutter and WordPress API Part 2



This is part 2 of my tutorial series Build Android Application using Flutter and WordPress API. If you didn’t read the first part please check it before you continue reading further.

Build Android application using Flutter and WordPress API

Part 2

Working with images

In this part I will try to explain how to load images from WordPress API and avoid some common errors. In the first part we used Image widget to load our post images in post Card like this:

main.dart
 new Image.network(posts[index]["_embedded"]["wp:featuredmedia"][0]["source_url"])

And this should work well for most of you guys, as long as all of your posts have featured image. But in case that some of your posts don’t have featured image you will get null error in your console similar to this one below:

Console
I/flutter ( 7147): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 7147): The following NoSuchMethodError was thrown during performLayout():
I/flutter ( 7147): The method '[]' was called on null.
I/flutter ( 7147): Receiver: null
I/flutter ( 7147): Tried calling: [](0)

Your flutter widgets won’t be rendered and you will see only blank page. Before we try to load image in our Image widget we should check if post has featured image. This is quite easy thing to do because WordPress API returns featured_image property for each post in it’s response. This property basically is featured image id. But in case when post doesn’t have any featured image set its value will be 0. So simply by checking value of posts[index][‘featured_media’] we can know if post has featured image and then get it’s url to load it in Image widget. Update your application code like this:

main.dart
new Image.network(
    posts[index]['featured_media'] == 0
    ? '' // post doesn't have image
    : posts[index]["_embedded"]["wp:featuredmedia"][0]["source_url"]
)

What I have here is just basic shorthand if statement. If value is 0 i will just pass empty string but you could easily add placeholder image if you want. If value isn’t 0 we will fetch image link and show image.

Fade in images

Ok now we have our post images showing in Cards but we have problem how they are just poping into view from nowhere when they are loaded. That’s more like you see images loading in web browser on some web pages. We are working on android application and we want to make images loading smooth as possible. Lets make them fade in.

Transparent image

We can achieve fade in effect on our images easily by using Transparent image package by Brian Egan. To install it in your project add it to your dependencies in pubspec.yaml file:

main.dart
dependencies:
  flutter:
    sdk: flutter
  transparent_image: ^0.1.0

After you have it in your dependencies you can get it with:

Console
flutter packages get

Now just import it in our main.dart file:

main.dart
import 'package:transparent_image/transparent_image.dart';

Implementation

Transparent image package is installed and now we can use it in our application easily. I will replace Image widget with:

main.dart
new FadeInImage.memoryNetwork(
                      placeholder: kTransparentImage,
                      image: posts[index]["featured_media"] == 0
                             ? '' // post doesn't have image
                             : posts[index]["_embedded"]["wp:featuredmedia"][0]["source_url"],
                      )

You can see that we are using FadeInImage widget which comes packaged with Flutter. For placeholder image we are using transparent image from Transparent image package we installed. Image code is same we used with original Image widget. We are again checking if post has featured image and loading it if that’s true. Now if you start your application on your phone or in emulator you will see images fading in while they are being loaded. With just this little touch your application will look much better, more polished and professional. This is all in part 2 of Build Android Application using Flutter and WordPress API tutorial. More parts are coming soon. Please check full application code bellow:

main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:transparent_image/transparent_image.dart';

void main() {
  runApp(MaterialApp(
      home: VirtuoozaHome()
  ));
}

class VirtuoozaHome extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => VirtuoozaHomeState();
}

class VirtuoozaHomeState extends State<VirtuoozaHome> {

  // Base URL for our wordpress API
  final String apiUrl = "https://virtuooza.com/wp-json/wp/v2/";
  // Empty list for our posts
  List posts;

  // Function to fetch list of posts
   Future<String> getPosts() async {

    var res = await http.get(Uri.encodeFull(apiUrl + "posts?_embed"), headers: {"Accept": "application/json"});

    // fill our posts list with results and update state
    setState(() {
      var resBody = json.decode(res.body);
      posts = resBody;
    });

    return "Success!";
  }

  @override
  void initState() {
    super.initState();
    this.getPosts();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Virtuooza"),
        backgroundColor: Colors.blueAccent
      ),
      body: ListView.builder(
        itemCount: posts == null ? 0 : posts.length,
        itemBuilder: (BuildContext context, int index) {
          return Column(
            children: <Widget>[
              Card(
                child: Column(
                  children: <Widget>[
                     new FadeInImage.memoryNetwork(
                      placeholder: kTransparentImage,
                        image: posts[index]["featured_media"] == 0
                               ? 'images/placeholder.png'
                               : posts[index]["_embedded"]["wp:featuredmedia"][0]["source_url"],
                      ),
                    new Padding(
                      padding: EdgeInsets.all(10.0),
                      child: new ListTile(
                        title: new Padding(
                             padding: EdgeInsets.symmetric(vertical: 10.0), 
                             child: new Text(posts[index]["title"]["rendered"])),
                        subtitle: new Text(
                           posts[index]["excerpt"]["rendered"].replaceAll(new RegExp(r'<[^>]*>'), '')
                       ),
                      ),
                    )
                  ],
                ),
              )
            ],
          );
        },
      ),
    );
  }
}



Share with your friends