将 strapi 数据导入 Flutter
Get strapi datas into Flutter
*After many documentations readed, I saw that Flutter is not compatible with strapi v4, to use it with Flutter, you have to use a
strapi project under v4.
我正在尝试将我的 Flutter 应用连接到 Strapi。
我关注了 Flutter 的官方 Strapi tuto 和 Youtube 上的一些视频,但我坚持阅读数据。
我在开始查看时遇到此错误:
_TypeError(类型“_InternalLinkedHashMap”不是类型 'Iterable' 的子类型)
这是这个视图的完整代码:
import 'dart:convert';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:strapitests/user.dart';
class MyList extends StatefulWidget {
const MyList({Key? key}) : super(key: key);
@override
State<MyList> createState() => _MyListState();
}
class _MyListState extends State<MyList> {
List<User> users = [];
Future getAll() async {
var data = await http.get(Uri.parse("http://10.0.2.2:1337/api/apis"));
var jsonData = json.decode(data.body);
for (var u in jsonData) {
users.add(
u['name'],
);
}
return users;
}
@override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: getAll(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: const Center(
child: Text("Loading..."),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].name),
subtitle: Text(snapshot.data[index].email),
);
},
);
}
},
),
);
}
}
这是我的 'User' class:
class User {
String name;
String email;
String password;
User(this.name, this.email, this.password);
}
当我在我的浏览器上创建 'GET' 时,结果是:
"data": [
{
"id": 1,
"attributes": {
"name": "john",
"password": "dfdf",
"email": "test@gmail.com",
"createdAt": "2022-05-23T20:38:27.725Z",
"updatedAt": "2022-05-23T20:38:28.466Z",
"publishedAt": "2022-05-23T20:38:28.464Z"
}
},
{
"id": 2,
"attributes": {
"name": "text",
"password": "mp",
"email": "mail",
"createdAt": "2022-05-23T20:47:56.717Z",
"updatedAt": "2022-05-23T20:47:56.717Z",
"publishedAt": "2022-05-23T20:47:56.712Z"
}
},
{
"id": 3,
"attributes": {
"name": "name",
"password": "mp",
"email": "mail",
"createdAt": "2022-05-23T20:52:07.911Z",
"updatedAt": "2022-05-23T20:52:07.911Z",
"publishedAt": "2022-05-23T20:52:07.910Z"
}
}
],
感谢您的帮助!
首先,您需要从 JSON 解码您的用户。由于这是一个简单的 class,您可以为 User
class:
编写一个快速的 fromJson
构造函数
class User {
String name;
String email;
String password;
User(this.name, this.email, this.password);
factory User.fromJson(Map<String, dynamic> json) {
final attributes = json['attributes'];
return User(
attributes['name'],
attributes['email'],
attributes['password'],
);
}
}
接下来,您接收的数据是地图,无法使用 for-loop 迭代。
相反,迭代由 "data"
键入的列表,并使用我们刚刚定义的 User.fromJson
构造函数解码每个元素:
Future<List<User>> getAll() async {
var data = await http.get(Uri.parse("http://10.0.2.2:1337/api/apis"));
var jsonData = json.decode(data.body);
final users = jsonData['data'];
return users.map((userJson) => User.fromJson(userJson)).toList();
}
最后,由于您使用的是 FutureBuilder
,实际上您不需要将其作为有状态小部件,也不需要将 users
存储为 属性 在你的 class 上。您可以简单地使用快照中返回的列表 - 虽然您需要更改代码以使 Future 成为最终成员,以便小部件不会在每次构建时构建新的未来:
class MyList extends StatelessWidget {
late final Future<List<User>> users = getAll();
@override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: users,
// ...
),
);
}
}
另外——这与你的问题无关——但是研究避免在服务器上存储密码的方法是个好主意。如果您确实存储了密码,请绝对避免在生产应用的任何 API 响应中返回它们 :).
这里有几篇关于该主题的好文章:
https://auth0.com/blog/hashing-passwords-one-way-road-to-security/
https://auth0.com/blog/adding-salt-to-hashing-a-better-way-to-store-passwords/
*After many documentations readed, I saw that Flutter is not compatible with strapi v4, to use it with Flutter, you have to use a strapi project under v4.
我正在尝试将我的 Flutter 应用连接到 Strapi。
我关注了 Flutter 的官方 Strapi tuto 和 Youtube 上的一些视频,但我坚持阅读数据。
我在开始查看时遇到此错误:
_TypeError(类型“_InternalLinkedHashMap
这是这个视图的完整代码:
import 'dart:convert';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:strapitests/user.dart';
class MyList extends StatefulWidget {
const MyList({Key? key}) : super(key: key);
@override
State<MyList> createState() => _MyListState();
}
class _MyListState extends State<MyList> {
List<User> users = [];
Future getAll() async {
var data = await http.get(Uri.parse("http://10.0.2.2:1337/api/apis"));
var jsonData = json.decode(data.body);
for (var u in jsonData) {
users.add(
u['name'],
);
}
return users;
}
@override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: getAll(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: const Center(
child: Text("Loading..."),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].name),
subtitle: Text(snapshot.data[index].email),
);
},
);
}
},
),
);
}
}
这是我的 'User' class:
class User {
String name;
String email;
String password;
User(this.name, this.email, this.password);
}
当我在我的浏览器上创建 'GET' 时,结果是:
"data": [
{
"id": 1,
"attributes": {
"name": "john",
"password": "dfdf",
"email": "test@gmail.com",
"createdAt": "2022-05-23T20:38:27.725Z",
"updatedAt": "2022-05-23T20:38:28.466Z",
"publishedAt": "2022-05-23T20:38:28.464Z"
}
},
{
"id": 2,
"attributes": {
"name": "text",
"password": "mp",
"email": "mail",
"createdAt": "2022-05-23T20:47:56.717Z",
"updatedAt": "2022-05-23T20:47:56.717Z",
"publishedAt": "2022-05-23T20:47:56.712Z"
}
},
{
"id": 3,
"attributes": {
"name": "name",
"password": "mp",
"email": "mail",
"createdAt": "2022-05-23T20:52:07.911Z",
"updatedAt": "2022-05-23T20:52:07.911Z",
"publishedAt": "2022-05-23T20:52:07.910Z"
}
}
],
感谢您的帮助!
首先,您需要从 JSON 解码您的用户。由于这是一个简单的 class,您可以为 User
class:
fromJson
构造函数
class User {
String name;
String email;
String password;
User(this.name, this.email, this.password);
factory User.fromJson(Map<String, dynamic> json) {
final attributes = json['attributes'];
return User(
attributes['name'],
attributes['email'],
attributes['password'],
);
}
}
接下来,您接收的数据是地图,无法使用 for-loop 迭代。
相反,迭代由 "data"
键入的列表,并使用我们刚刚定义的 User.fromJson
构造函数解码每个元素:
Future<List<User>> getAll() async {
var data = await http.get(Uri.parse("http://10.0.2.2:1337/api/apis"));
var jsonData = json.decode(data.body);
final users = jsonData['data'];
return users.map((userJson) => User.fromJson(userJson)).toList();
}
最后,由于您使用的是 FutureBuilder
,实际上您不需要将其作为有状态小部件,也不需要将 users
存储为 属性 在你的 class 上。您可以简单地使用快照中返回的列表 - 虽然您需要更改代码以使 Future 成为最终成员,以便小部件不会在每次构建时构建新的未来:
class MyList extends StatelessWidget {
late final Future<List<User>> users = getAll();
@override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: users,
// ...
),
);
}
}
另外——这与你的问题无关——但是研究避免在服务器上存储密码的方法是个好主意。如果您确实存储了密码,请绝对避免在生产应用的任何 API 响应中返回它们 :).
这里有几篇关于该主题的好文章:
https://auth0.com/blog/hashing-passwords-one-way-road-to-security/
https://auth0.com/blog/adding-salt-to-hashing-a-better-way-to-store-passwords/