0

This is my first month as coder. I am trying to develop nearby places app. When i used following codes im getting error of "null check operator used on a null value". But based on what i see or when i printed url and checked manually or when i used if condition i see no problem or no error. Just when i rendered screen im getting this error. I would like to ask if someone can point me what is wrong ? Thanks in advance!

The line im getting error is locationName: locationSuggestion!.query.pages[0]!.title. Probibly and following locationSuggestion class.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_udemy_examples/http_api_data/get_location_data_final.dart';
import 'package:flutter_udemy_examples/http_api_data/get_location_names.dart';
import 'package:flutter_udemy_examples/screens/login_ekrani.dart';
import 'package:flutter_udemy_examples/screens/map_screen.dart';
import 'login_ekrani.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../banner.dart';
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http;

import 'package:flutter_udemy_examples/http_api_data/get_location_images.dart';

// ignore: must_be_immutable
class HomeScreen extends StatefulWidget {
  @override
  State<HomeScreen> createState() => HomeScreenState();
}

class HomeScreenState extends State<HomeScreen> {
  LocationDataFinal? locationSuggestion;

  bool isLoading = true;
  @override
  void initState() {
    super.initState();
    asyncInitState();
  }

  Future<void> asyncInitState() async {
    await fecthlocationData();
  }

  Future fecthlocationData() async {
    var locations = await Geolocator.getCurrentPosition(
      desiredAccuracy: LocationAccuracy.high,
    );

    final double enlem = locations.latitude;
    final double boylam = locations.longitude;
    final url = Uri.parse(
        "https://en.wikipedia.org/w/api.php?action=query&format=json&prop=coordinates%7Cpageimages%7Cdescription%7Cextracts&generator=geosearch&piprop=original&descprefersource=central&exlimit=20&exintro=1&explaintext=1&exsectionformat=plain&ggscoord=${enlem}%7C${boylam}&ggsradius=10000");
    print(url);
    final response = await http.get(url);
    //print(response.body);
    if (response.statusCode == 200) {
      locationSuggestion = await locationDataFinalFromJson(response.body);
      if (locationSuggestion != null) {
        setState(() {
          isLoading = false;
        });
      } else {
        print("null1");
      }
    } else {
      print("null2");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: _buildAppBar(context),
      body: isLoading
          ? Center(
              child: CircularProgressIndicator(),
            )
          : ListView(
              children: [
                MyBanner(
                  // info: locationSuggestion!.query.pages[0]!.description,
                  locationName: locationSuggestion!.query.pages[0]!.title,
                  imagePath:
                      locationSuggestion!.query.pages[0]!.original.source,
                  context: context,
                ),
                MyBanner(
                  //info: locationSuggestion!.query.pages[1]!.description,
                  locationName: locationSuggestion!.query.pages[1]!.title,
                  imagePath:
                      locationSuggestion!.query.pages[1]!.original.source,
                  context: context,
                ),
                MyBanner(
                  //  info: locationSuggestion!.query.pages[2]!.description,
                  locationName: locationSuggestion!.query.pages[2]!.title,
                  imagePath:
                      locationSuggestion!.query.pages[2]!.original.source,
                  context: context,
                ),
                MyBanner(
                  //  info: locationSuggestion!.query.pages[3]!.description,
                  locationName: locationSuggestion!.query.pages[3]!.title,
                  imagePath:
                      locationSuggestion!.query.pages[3]!.original.source,
                  context: context,
                ),
                MyBanner(
                  //  info: locationSuggestion!.query.pages[4]!.description,
                  locationName: locationSuggestion!.query.pages[4]!.title,
                  imagePath:
                      locationSuggestion!.query.pages[4]!.original.source,
                  context: context,
                ),
              ],
            ),
    );
  }

  AppBar _buildAppBar(BuildContext context) {
    return AppBar(
      automaticallyImplyLeading: false,
      leading: RotatedBox(
        quarterTurns: 2,
        child: _buildExitButton(context),
      ),
      actions: [
        _buildOpenMapButton(),
        _buildCallEmergencyNumberButton(),
      ],
      titleSpacing: 25,

      shadowColor: Colors.white,
      elevation: 0.0,
      backgroundColor: Colors.blue[800],
      //titleSpacing: Padding(padding: EdgeInsets.fromLTRB(25.85.0, 0, 25.85.0, 0)),
      title: Text("Traveler Doctor"),
    );
  }

  Widget _buildCallEmergencyNumberButton() {
    return IconButton(
      disabledColor: Colors.red,
      color: Colors.red,
      icon: Icon(Icons.phone_enabled),
      tooltip: "Local emergency number",
      onPressed: null,
    );
  }

  Widget _buildOpenMapButton() {
    return IconButton(
      disabledColor: Colors.orangeAccent,
      color: Colors.limeAccent,
      icon: Icon(Icons.map_rounded),
      tooltip: "Map",
      enableFeedback: false,
      onPressed: () => {
        Navigator.push(context,
            MaterialPageRoute(builder: (BuildContext context) => MapScreen()))
      },
    );
  }
}

Widget _buildExitButton(BuildContext context) {
  return IconButton(
    onPressed: () async {
      final SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setString('KullaniciAdi', "");

      Navigator.pushReplacement(context,
          MaterialPageRoute(builder: (BuildContext context) => LoginEkrani()));
    },
    icon: Icon(
      Icons.exit_to_app,
      color: Colors.red,
    ),
    tooltip: "Exit",
  );
}


And this is the model im using for parsing api response

import 'dart:convert';

LocationDataFinal locationDataFinalFromJson(String str) =>
    LocationDataFinal.fromJson(json.decode(str));

class LocationDataFinal {
  LocationDataFinal({
    required this.batchcomplete,
    required this.query,
  });

  String batchcomplete;
  Query query;

  factory LocationDataFinal.fromJson(Map<String, dynamic> json) =>
      LocationDataFinal(
        batchcomplete: json["batchcomplete"],
        query: Query.fromJson(json["query"]),
      );
}

class Query {
  Query({
    required this.pages,
  });

  Map<String, Page> pages;

  factory Query.fromJson(Map<String, dynamic> json) => Query(
        pages: Map.from(json["pages"])
            .map((k, v) => MapEntry<String, Page>(k, Page.fromJson(v))),
      );
}

class Page {
  Page({
    required this.pageid,
    required this.ns,
    required this.title,
    required this.index,
    required this.coordinates,
    required this.original,
    required this.description,
    required this.descriptionsource,
    required this.extract,
  });

  int pageid;
  int ns;
  String title;
  int index;
  List<Coordinate> coordinates;
  Original original;
  String description;
  String descriptionsource;
  String extract;

  factory Page.fromJson(Map<String, dynamic> json) => Page(
        pageid: json["pageid"],
        ns: json["ns"],
        title: json["title"],
        index: json["index"],
        coordinates: List<Coordinate>.from(
            json["coordinates"].map((x) => Coordinate.fromJson(x))),
        original: json["original"] == null
            ? Original(
                source:
                    "https://tigres.com.tr/wp-content/uploads/2016/11/orionthemes-placeholder-image-1.png",
                width: 300,
                height: 200)
            : Original.fromJson(json["original"]),
        description: json["description"] == null ? "asd" : json["description"],
        descriptionsource:
            json["descriptionsource"] == null ? " " : json["descriptionsource"],
        extract: json["extract"],
      );
}

class Coordinate {
  Coordinate({
    required this.lat,
    required this.lon,
    required this.primary,
    required this.globe,
  });

  double lat;
  double lon;
  String primary;
  Globe globe;

  factory Coordinate.fromJson(Map<String, dynamic> json) => Coordinate(
        lat: json["lat"].toDouble(),
        lon: json["lon"].toDouble(),
        primary: json["primary"],
        globe: globeValues.map[json["globe"]]!,
      );
}

enum Globe { EARTH }

final globeValues = EnumValues({"earth": Globe.EARTH});

class Original {
  Original({
    required this.source,
    required this.width,
    required this.height,
  });

  String source;
  int width;
  int height;

  factory Original.fromJson(Map<String, dynamic> json) => Original(
        source: json["source"],
        width: json["width"],
        height: json["height"],
      );
}

class EnumValues<T> {
  late Map<String, T> map;
  late Map<T, String> reverseMap;

  EnumValues(this.map);
}

I will be checking this post frequently. Thanks in advance again. Sincerely ur noob coder.

2 Answers 2

1

Would leave this as a comment but apparently I only have enough reputation to write answers.

In your Query object pages is a Map<String, Page> but you're accessing it with a int key: locationSuggestion!.query.pages[0]!.title

To access the map with an int key, it needs to be Map<int,Page> (or List<Page>)

Sign up to request clarification or add additional context in comments.

8 Comments

Hey @Pat9RB Thnx for your answer! ` factory LocationDataFinal.fromJson(Map<String, dynamic> json) => LocationDataFinal( batchcomplete: json["batchcomplete"], query: Query.fromJson(json["query"]), ` ur solutions seems like some what improves but this time the code section i gave at top gives an error. Such as ""_TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Map<int, dynamic>')"" Any idea ?
Dart::convert json.decode() converts json to Map<String,dynamic>. If you want to use the values as some other type you need to convert it. For example, if you have the json {"label": "value"} then want to use "value" as a String, you would have to cast it: Map<String, dynamic> json = json.decode('{"label": "value"}'); String myString = json["label"] as String; If you can post an example of your json (or an example of a URL you're using to fetch it with the values filled in) I can probably be more help with how to access it.
Thanks for your patience! this is the api url im getting data from. If i were to convert pages to list instead of map would it solve problem ? Since every element of pages is a map ?link
You could keep the existing implementation of pages as a Map<String, Page> and, instead of calling locationSuggestion!.query.pages[0]!.title, call locationSuggestion!.query.pages.entries.first.value.title. Note that, Iterable.first returns a non-nullable type, but will throw a StateError if empty, so it would be worth ensuring locationSuggestion!.query.pages.isNotEmpty before accessing it.
Looking at your JSON source, "pages" is converted to a Map<String,Map<String,dynamic>> because "pages" is an object ( "{}" ) that contains a bunch of objects. You can get a List of the keys contained in "pages" using pages.keys, and access each pages child object like pages[pages.keys[0]]. Keep everything Map<String, dynamic> (not Map<Int,...>) and try accessing different pages with locationSuggestion!.query.pages[pages.keys[0]]
|
0

Somewhat i solved issue by replacing locationSuggestion!.query.pages[0]!.titlewith

locationSuggestion!.query.pages.values.elementAt(0).title This way of adressing solved issue for me :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.