Flutter crash when theres no internet

Viewed 1816

my app (literally took it from here) crashes whenever i disable internet connection, works like a charm with internet. how can i still able to access the page, displaying the last accessed result without getting stuck? i have all the internet permission included in manifest.

<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

this is the code

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Future<Album> fetchAlbum() async {
  final response =
      await http.get('https://jsonplaceholder.typicode.com/albums/1');

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response, then parse the JSON.
    return Album.fromJson(json.decode(response.body));
  } else {
    // If the server did not return a 200 OK response, then throw an exception.
    throw Exception('Failed to load album');
  }
}

class Album {
  final int userId;
  final int id;
  final String title;

  Album({this.userId, this.id, this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
    );
  }
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
Future<Album> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<Album>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data.title);
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }

              // By default, show a loading spinner.
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

Thank you

3 Answers

You can use connectivity library to listen for wifi status

import 'package:connectivity/connectivity.dart';

@override
initState() {
  super.initState();

  subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
    // Got a new connectivity status!
  })
}

// Be sure to cancel subscription after you are done
@override
dispose() {
  super.dispose();

  subscription.cancel();
}

Use the Connectivity library to check network status, before making any HTTP requests.

The simplest solution, with no additional packages, is to put the code that connects to the internet in try/catch block. You must return a default object of Album, an empty list [] in case there is a list of Albums, in the catch block or throw an exception.

In your case, the code can be like this:

Future<Album> fetchAlbum() async {
      try{
        final response = await http.get('https://jsonplaceholder.typicode.com/albums/1');
        if (response.statusCode == 200) {
        // If the server did return a 200 OK response, then parse the JSON.
          return Album.fromJson(json.decode(response.body));
        } else {
          // If the server did not return a 200 OK response, then throw an exception.
          throw Exception('Failed to load album');
        }
      } catch(_){
        print("No Internet Connection");
        return Album(userId=-1, id=-1, title=''});
    }

You can show a message to the user indicating the problem. You can do it like this:

showDialog(
                context: context,
                builder: (_) => AlertDialog(
                      title: Text('No Internet Connection',
                          style: TextStyle(
                              color: Colors.red, fontWeight: FontWeight.bold)),
                      content: Text('No Internet Connection. Please connect to the internet and try again'),
                    ),
                barrierDismissible: true);
Related