#android #ios #api #flutter #dart
#Android #iOS #API #флаттер #dart
Вопрос:
Я пытаюсь создать приложение pokemon. Но я получаю эту ошибку:
«Получатель «pokemon» был вызван при null.
Получатель: null
Пытался вызвать: pokemon»
Я использую этот URL-адрес API для получения данных «https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json »
И мой класс Pokemon здесь:
class PokeHub {
List<Pokemon> pokemon;
PokeHub({this.pokemon});
PokeHub.fromJson(Map<String,dynamic> json) {
if (json['pokemon'] != null) {
pokemon = new List<Pokemon>();
json['pokemon'].forEach((items) {
pokemon.add(new Pokemon.fromJson(items));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.pokemon != null) {
data['pokemon'] = this.pokemon.map((items) => items.toJson()).toList();
}
return data;
}
}
class Pokemon {
int id;
String num;
String name;
String img;
List<String> type;
String height;
String weight;
String candy;
int candyCount;
String egg;
String spawnChance;
String avgSpawns;
String spawnTime;
List<double> multipliers;
List<String> weaknesses;
List<NextEvolution> nextEvolution;
Pokemon(
{this.id,
this.num,
this.name,
this.img,
this.type,
this.height,
this.weight,
this.candy,
this.candyCount,
this.egg,
this.spawnChance,
this.avgSpawns,
this.spawnTime,
this.multipliers,
this.weaknesses,
this.nextEvolution});
Pokemon.fromJson(Map<String, dynamic> json) {
id = json['id'];
num = json['num'];
name = json['name'];
img = json['img'];
type = json['type'].cast<String>();
height = json['height'];
weight = json['weight'];
candy = json['candy'];
candyCount = json['candy_count'];
egg = json['egg'];
spawnChance = json['spawn_chance'].toString();
avgSpawns = json['avg_spawns'].toString();
spawnTime = json['spawn_time'];
multipliers = json['multipliers']?.cast<double>();
weaknesses = json['weaknesses'].cast<String>();
if (json['next_evolution'] != null) {
nextEvolution = new List<NextEvolution>();
json['next_evolution'].forEach((v) {
nextEvolution.add(new NextEvolution.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['num'] = this.num;
data['name'] = this.name;
data['img'] = this.img;
data['type'] = this.type;
data['height'] = this.height;
data['weight'] = this.weight;
data['candy'] = this.candy;
data['candy_count'] = this.candyCount;
data['egg'] = this.egg;
data['spawn_chance'] = this.spawnChance;
data['avg_spawns'] = this.avgSpawns;
data['spawn_time'] = this.spawnTime;
data['multipliers'] = this.multipliers;
data['weaknesses'] = this.weaknesses;
if (this.nextEvolution != null) {
data['next_evolution'] =
this.nextEvolution.map((v) => v.toJson()).toList();
}
return data;
}
}
class NextEvolution {
String num;
String name;
NextEvolution({this.num, this.name});
NextEvolution.fromJson(Map<String, dynamic> json) {
num = json['num'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['num'] = this.num;
data['name'] = this.name;
return data;
}
И это мой основной файл.dart:
import 'package:flutter/material.dart';
import 'package:pokemon_flutter/screens/main_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Poke App",
home: MainScreen(),
debugShowCheckedModeBanner: false,
);
}
}
И это мой main_screen.файл dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:pokemon_flutter/models/pokemon.dart';
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
var url =
"https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json";
PokeHub pokeHub;
@override
void initState() {
super.initState();
fetchData();
}
void fetchData() async {
var res = await http.get(url);
var decodedJson = jsonDecode(res.body);
pokeHub = PokeHub.fromJson(decodedJson);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Poke App"),
backgroundColor: Colors.cyan,
),
body: GridView.count(
crossAxisCount: 2,
children: pokeHub.pokemon.map((poke) => Card()).toList(),
),
drawer: Drawer(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: Colors.cyan,
child: Icon(Icons.refresh),
),
);
}
}
Похоже, что все верно, поэтому я не могу распознать ошибку. Если у вас есть совет по этой ситуации, я буду признателен.
Редактировать: я новичок здесь, поэтому иногда мои вопросы могут быть бессмысленными.Но, пожалуйста, не уменьшайте мои очки. Stackoverflow больше не будет принимать мои вопросы. Пожалуйста, увеличьте мои очки.
Ответ №1:
когда я закончил свой код, приложение сработало. Вот мой новый main_screen.файл dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:pokemon_flutter/models/pokemon.dart';
import 'package:pokemon_flutter/screens/pokemon_detail_screen.dart';
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
var url =
"https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json";
PokeHub pokeHub;
@override
void initState() {
super.initState();
fetchData();
}
var res;
void fetchData() async {
res= await http.get(url);
var decodedJson = jsonDecode(res.body);
pokeHub = PokeHub.fromJson(decodedJson);
print(pokeHub.toJson());
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Poke App"),
backgroundColor: Colors.cyan,
),
body: pokeHub == null
? Center(
child: CircularProgressIndicator(),
)
: GridView.count(
crossAxisCount: 2,
children: pokeHub.pokemon
.map((poke) => Padding(
padding: const EdgeInsets.all(2.0),
child: InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>PokeDetail(
pokemon: poke,
)));
},
child: Hero(
tag: poke.img,
child: Card(
elevation: 3.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(poke.img))),
),
Text(
poke.name,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
)
],
),
),
),
),
))
.toList(),
),
drawer: Drawer(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: Colors.cyan,
child: Icon(Icons.refresh),
),
);
}
}
Я добавил оператор if else и установил состояние. Я не знаю, как я решил эту проблему, но она была решена.
Я думаю, что эти коды сработали:
void fetchData() async {
res= await http.get(url);
var decodedJson = jsonDecode(res.body);
pokeHub = PokeHub.fromJson(decodedJson);
print(pokeHub.toJson());
setState(() {});
}
body: pokeHub == null
? Center(
child: CircularProgressIndicator(),
)
: GridView.count(
Ответ №2:
Когда вы вызываете pokeHub.pokemon, pokeHub по-прежнему имеет значение null, поэтому он не может вернуть какое-либо значение для pokemon getter. Я вижу, что вы извлекаете данные, но когда ваш виджет собран, эти данные (которые возвращаются асинхронно) еще не были возвращены. В этом случае это будет хорошим выбором с использованием FutureBuilder. Что-то вроде этого должно работать:
var res;
void fetchData() {
res = http.get(url).then((value){
var decodedJson = jsonDecode(res.body);
pokeHub = PokeHub.fromJson(decodedJson);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Poke App"),
backgroundColor: Colors.cyan,
),
body: FutureBuilder(
future: res,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData)
return GridView.count(
crossAxisCount: 2,
children: pokeHub.pokemon.map((poke) => Card()).toList(),
),
drawer: Drawer(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: Colors.cyan,
child: Icon(Icons.refresh),
);
},
),
);
}
Это (своего рода) использует futurebuilder для создания виджетов только после получения данных. Дополнительная информация: https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
Комментарии:
1. Спасибо за ваш совет. Но я решил проблему. Теперь я собираюсь отредактировать свой вопрос. Хорошего дня!