Оператор проверки флаттера на нуль, используемый для нулевого значения

#flutter #dart

Вопрос:

Это мой первый месяц в качестве программиста. Я пытаюсь разработать приложение «близлежащие места». Когда я использовал следующие коды, я получал ошибку «оператор проверки null, используемый для нулевого значения». Но на основании того, что я вижу, или когда я напечатал URL и проверил вручную, или когда я использовал условие if, я не вижу проблем или ошибок. Как раз когда я визуализировал экран, я получил эту ошибку. Я хотел бы спросить, может ли кто-нибудь указать мне, в чем дело ? Заранее спасибо!

Строка, в которой я получаю ошибку, — это LocationName: locationSuggestion!.запрос.страницы[0]!.заголовок. Вероятностно и в соответствии с классом определения местоположения.

 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=queryamp;format=jsonamp;prop=coordinates|pageimages|description|extractsamp;generator=geosearchamp;piprop=originalamp;descprefersource=centralamp;exlimit=20amp;exintro=1amp;explaintext=1amp;exsectionformat=plainamp;ggscoord=${enlem}|${boylam}amp;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",
  );
}


 

И это модель, которую я использую для анализа ответа api

 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);
}

 

Я буду часто проверять этот пост.
Еще раз заранее спасибо.
Искренне ваш программист-нуб.

Ответ №1:

Я бы оставил это в качестве комментария, но, по-видимому, у меня достаточно репутации, чтобы писать ответы.

На страницах объекта запроса есть a Map<String, Page> , но вы обращаетесь к нему с помощью ключа int: locationSuggestion!.query.pages[0]!.title

Чтобы получить доступ к карте с помощью ключа int, он должен быть Map<int,Page> (или List<Page> )

Комментарии:

1. Привет @Pat9RB Thnx за твой ответ! ` factory LocationDataFinal.FromJSON(Карта<Строка, динамический> json) =<Строка, динамический>> LocationDataFinal( пакетное выполнение: json[«пакетное выполнение»], запрос: Запрос.Из json(json[«запрос»])», решения ur, похоже, улучшаются, но на этот раз раздел кода, который я привел вверху, выдает ошибку. Например, «»_TypeError (тип «_InternalLinkedHashMap<Строка, динамическая>» не является подтипом типа » Карта<Строка, динамическая><int, динамическая>»)»» Есть идеи ?

2. Dart::преобразование json.decode() преобразует json в отображение<Строка,динамическая>. Если вы хотите использовать значения как какой-то другой тип, вам нужно его преобразовать. Например, если у вас есть json {«метка»: «значение»}, а затем вы хотите использовать «значение» в качестве строки, вам нужно будет привести его: Сопоставить<String, dynamic> json = json.decode(‘{«метка»: «значение»}’); Строка myString = json[«метка»] в качестве строки; Если вы можете опубликовать пример своего json (или пример URL-адреса, который вы используете для его извлечения с заполненными значениями) Я, вероятно, смогу больше помочь в том, как получить к нему доступ.

3. Спасибо за ваше терпение! это URL-адрес api, с которого я получаю данные. Если бы я преобразовал страницы в список вместо карты, это решило бы проблему ? Поскольку каждый элемент страниц-это карта ? ссылка

4. Вы могли бы сохранить существующую реализацию pages как Map<String, Page> и, вместо вызова locationSuggestion!.query.pages[0]!.title , позвонить locationSuggestion!.query.pages.entries.first.value.title . Обратите внимание, что, Iterable.first возвращает тип, не допускающий значения null, но будет выдавать StateError значение, если оно пустое, поэтому стоит убедиться locationSuggestion!.query.pages.isNotEmpty , прежде чем обращаться к нему.

5. Глядя на ваш источник JSON, «страницы» преобразуются в a Map<String,Map<String,dynamic>> , потому что «страницы» — это объект ( «{}» ), содержащий множество объектов. Вы можете получить List ключи , содержащиеся в разделе «страницы», с помощью pages.keys и получить доступ к каждому дочернему объекту страницы, например pages[pages.keys[0]] . Сохраните все на карте<String, dynamic> (не на карте<String, dynamic><Int,…>) и попробуйте получить доступ к разным страницам с помощью locationSuggestion!.query.pages[pages.keys[0]]

Ответ №2:

Несколько я решил проблему, заменив locationSuggestion!.query.pages[0]!.title на

locationSuggestion!.query.pages.values.elementAt(0).title Этот способ решения проблемы решил для меня 🙂