Riverpod:摄取 REST 的简单方法 API
Riverpod: Simple way to ingest REST API
我目前正在构建一个应用程序,它正在摄取 WordPress REST API 来显示博客文章。在初始应用程序加载时,我想让它使用一种方法提取初始数据,然后通过用户交互提取更多帖子。我目前有这个工作,但是,我的实现似乎很复杂,可能有一种更简洁的方法来实现这个工作。我的实现基于 this GitHub issue response。这是我的代码的样子:
在main.dart
中:
final blogRepository = FutureProvider((ref) async {
final posts = await getPosts();
return BlogService(posts);
},
);
final blogProvider = StateNotifierProvider<BlogService, List<BlogPost>>((ref) => throw UnimplementedError(
"Access to a [BlogService] should be provided through a [ProviderScope]."));
在blogservice.dart
中:
class BlogService extends StateNotifier<List<BlogPost>> {
final List<BlogPost> _posts;
BlogService(this._posts) : super(_posts);
List<BlogPost> get posts => _posts;
Future<void> morePosts(int length) async {
Response response;
var dio = Dio();
response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/?offset=' + length.toString());
var posts = (response.data as List);
state = [...state, ...posts.map((post) => BlogPost.fromJson(post)).toList()];
}
}
Future<List<BlogPost>> getPosts() async {
Response response;
var dio = Dio();
response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/');
var posts = (response.data as List);
return posts.map((post) => BlogPost.fromJson(post)).toList();
}
我认为更好的方法是使用 AsyncValue
,但是,我找不到任何使用 API 的好的参考实现。
请最好创建另一个 class 以提供来自 Api 的数据并使用漂移包
查看我的屏幕我如何从数据库提供数据(漂移是 sqlite DB)
这是我的数据库 class 基于 sqlite(drift)
import 'dart:io';
import 'package:drift/native.dart';
import 'package:mobile_nsk/models/policy/driver.dart';
import 'package:mobile_nsk/models/policy/driver_converter.dart';
import 'package:mobile_nsk/models/policy/holders.dart';
import 'package:mobile_nsk/models/policy/holders_converter.dart';
import 'package:mobile_nsk/models/policy/vehicle.dart';
import 'package:mobile_nsk/models/policy/vehicle_converter.dart';
import 'package:path/path.dart' as p;
import 'package:drift/drift.dart';
import 'package:path_provider/path_provider.dart';
part 'database.g.dart';
LazyDatabase _openConnection()=> LazyDatabase(()async{
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'db.sqlite'));
return NativeDatabase(file,logStatements: true);
});
@DriftDatabase(tables: [Holders, Drivers, Vehicles])
class MyDatabase extends _$MyDatabase {
MyDatabase() : super(_openConnection());
// Для страхователя
Future<List<Holder>> getAllHolders() => select(holders).get();
Stream<List<Holder>> watchAllHolder() => select(holders).watch();
Future insertNewHolder(Holder holder) => into(holders).insert(holder, mode: InsertMode.insertOrReplace);
Future deleteHolder(Holder holder) => delete(holders).delete(holder);
Future<Holder> getHolderById(Holder holder)=> select(holders).getSingle();
Future insetData(Holder holder) => into(holders).insert(holder, mode: InsertMode.insertOrReplace);
Future updateHolder(Holder holder, int id, String phone) async
{
await update(holders)..where((tbl) => tbl.id.equals(id))..write(HoldersCompanion(phone: Value(phone)));
await into(holders).insert(holder, mode: InsertMode.insertOrReplace);
}
// Для Водителя
Future<List<Driver>> getAllDriver() => select(drivers).get();
Stream<List<Driver>> watchAllDriver() => select(drivers).watch();
Future insertNewDriver(Driver driver) => into(drivers).insert(driver, mode: InsertMode.insertOrReplace);
Future deleteDriver(Driver driver) => delete(drivers).delete(driver);
// Для транспорта
Future<List<Vehicle>> getAllVehicles() => select(vehicles).get();
Stream<List<Vehicle>> watchAllVehicle() => select(vehicles).watch();
Future insertNewVehicle(Vehicle vehicle) => into(vehicles).insert(vehicle, mode: InsertMode.insertOrReplace);
Future deleteVehicle(Vehicle vehicle) => delete(vehicles).delete(vehicle);
// всегда инкрементить версию схему если что то добавил/убрал/изменил/нахуевертил
@override
int get schemaVersion => 1;
}
这是我的支架模型(由 build_runner 生成)
import 'package:drift/drift.dart';
import 'package:json_annotation/json_annotation.dart' as j;
import 'package:mobile_nsk/database/database.dart';
import 'package:mobile_nsk/models/policy/holders_converter.dart';
@UseRowClass(Holder)
class Holders extends Table{
IntColumn get id => integer()();
TextColumn get firstName =>text()();
TextColumn get middleName => text()();
TextColumn get lastName => text()();
TextColumn get legalName => text()();
IntColumn get isIndividual => integer()();
TextColumn get iin => text()();
IntColumn get isResident => integer()();
TextColumn get phone => text()();
TextColumn get email => text()();
TextColumn get address => text()();
IntColumn get documentTypeId => integer()();
TextColumn get documentNumber => text()();
TextColumn get documentIssueDate => text()();
TextColumn get classType => text().named("class")();
TextColumn get birthDate => text()();
BoolColumn get isExperienced => boolean()();
BoolColumn get isPrivileged => boolean()();
TextColumn get holders =>
text().map(const HolderConverter()).nullable()();
@override
Set<Column> get primaryKey=> {id};
}
@j.JsonSerializable()
class Holder implements Insertable<Holder>{
final int id;
final String firstName;
final String middleName;
final String lastName;
final String legalName;
final int isIndividual;
final String iin;
final int isResident;
final String phone;
final String email;
final String address;
final int documentTypeId;
final String documentNumber;
final String documentIssueDate;
@j.JsonKey(name: "class")
final String classType;
final String birthDate;
final bool isExperienced;
final bool isPrivileged;
const Holder(this.id, this.firstName, this.middleName, this.lastName, this.legalName, this.isIndividual, this.iin, this.isResident, this.phone, this.email, this.address, this.documentTypeId, this.documentNumber, this.documentIssueDate, this.classType, this.birthDate, this.isExperienced, this.isPrivileged);
factory Holder.fromJson(Map<String, dynamic>json)=> Holder(
json['id'] as int,
json['firstName'] as String? ?? "",
json['middleName'] as String? ?? "",
json['lastName'] as String? ?? "",
json['legalName'] as String? ?? "",
json['isIndividual'] as int,
json['iin'] as String? ?? "",
json['isResident'] as int? ?? 0,
json['phone'] as String? ?? "",
json['email'] as String? ?? "",
json['address'] as String? ?? "",
json['documentTypeId'] as int? ?? 0,
json['documentNumber'] as String? ?? "",
json['documentIssueDate'] as String? ?? "",
json['class'] as String? ?? "",
json['birthDate'] as String? ?? "",
json['isExperienced'] as bool? ?? false,
json['isPrivileged'] as bool? ?? false,
);
Map<String, dynamic>toJson()=>{
'id': id,
'firstName':firstName,
'middleName': middleName,
'lastName': lastName,
'legalName': legalName,
'isIndividual': isIndividual,
'iin': iin,
'isResident': isResident,
'phone': phone,
'email': email,
'address': address,
'documentTypeId': documentTypeId,
'documentNumber': documentNumber,
'documentIssueDate': documentIssueDate,
'class': classType,
'birthDate': birthDate,
'isExperienced': isExperienced,
'isPrivileged': isPrivileged,
};
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
return HoldersCompanion(
id: Value(id),
firstName: Value(firstName),
middleName: Value(middleName),
lastName: Value(lastName),
legalName: Value(legalName),
isIndividual: Value(isIndividual),
iin: Value(iin),
isResident: Value(isResident),
phone: Value(phone),
email: Value(email),
address: Value(address),
documentTypeId: Value(documentTypeId),
documentNumber: Value(documentNumber),
documentIssueDate: Value(documentIssueDate),
classType: Value(classType),
birthDate: Value(birthDate),
isExperienced: Value(isExperienced),
isPrivileged: Value(isPrivileged)
).toColumns(nullToAbsent);
}
}
这是我从 api 到数据库
的代码插入
import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:mobile_nsk/database/database.dart';
import 'package:mobile_nsk/models/policy/holders.dart';
class HolderProvider {
String baseUrl = 'http://172.16.3.49:9096/api/v1';
Future<void> getHolder(
String iin,MyDatabase database
) async {
final response = await http.get(
Uri.parse(baseUrl + '/Customer/get_full_client?iin=$iin'),
headers: {'Content-Type': 'application/json'});
if (jsonDecode(response.body)['isExperienced'] != false) {
database.insertNewHolder(Holder.fromJson(jsonDecode(response.body)));
} else {
throw Exception();
}
}
}
这是一个使用 AsyncValue
的示例 - 它消除了 repository
让你的 service.dart 文件像这样:
final blogServiceProvider = Provider<BlogService>((ref) => BlogService());
class BlogService {
Future<AsyncValue<List<BlogPost>>> getBlogPost() async {
try {
var dio = Dio();
Response response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/');
var posts = (response.data as List);
List<BlogPost> list = posts.map<BlogPost>((post) => BlogPost.fromJson(post)).toList();
return AsyncData(list);
} catch (e) {
return AsyncError("Something went wrong");
}
}
}
你的供应商是这样的:
final blogNotifierProvider = StateNotifierProvider<BlogNotifier, AsyncValue<List<BlogPost>>>((ref){
BlogService _service = ref.read(blogServiceProvider);
return BlogNotifier(_service);
});
class BlogNotifier extends StateNotifier<AsyncValue<List<BlogPost>>> {
BlogNotifier(this._service) : super(AsyncLoading()) {
getPosts();
}
final BlogService _service;
void getPosts() async {
state = await _service.getBlogPost();
}
}
编辑:要将现有帖子与新帖子合并,试试这个:
class BlogService {
List<BlogPost> _posts = [];
Future<AsyncValue<List<BlogPost>>> getBlogPost() async {
try {
var dio = Dio();
Response response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/');
var posts = (response.data as List);
List<BlogPost> list = posts.map<BlogPost>((post) => BlogPost.fromJson(post)).toList();
_posts = list;
return AsyncData(list);
} catch (e) {
return AsyncError("Something went wrong");
}
}
Future<AsyncValue<List<BlogPost>>> morePosts() async {
try {
var dio = Dio();
Response response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/?offset=' + length.toString());
var posts = (response.data as List);
List<BlogPost> list = posts.map<BlogPost>((post) => BlogPost.fromJson(post)).toList();
_posts.addAll(list);
return AsyncData(_posts);
} catch (e) {
return AsyncError("Something went wrong");
}
}
}
通知者 class 将是:
class BlogNotifier extends StateNotifier<AsyncValue<List<BlogPost>>> {
BlogNotifier(this._service) : super(AsyncLoading()) {
getPosts();
}
final BlogService _service;
void getPosts() async {
state = await _service.getBlogPost();
}
void morePosts() async {
state = await _service.morePosts();
}
}
我目前正在构建一个应用程序,它正在摄取 WordPress REST API 来显示博客文章。在初始应用程序加载时,我想让它使用一种方法提取初始数据,然后通过用户交互提取更多帖子。我目前有这个工作,但是,我的实现似乎很复杂,可能有一种更简洁的方法来实现这个工作。我的实现基于 this GitHub issue response。这是我的代码的样子:
在main.dart
中:
final blogRepository = FutureProvider((ref) async {
final posts = await getPosts();
return BlogService(posts);
},
);
final blogProvider = StateNotifierProvider<BlogService, List<BlogPost>>((ref) => throw UnimplementedError(
"Access to a [BlogService] should be provided through a [ProviderScope]."));
在blogservice.dart
中:
class BlogService extends StateNotifier<List<BlogPost>> {
final List<BlogPost> _posts;
BlogService(this._posts) : super(_posts);
List<BlogPost> get posts => _posts;
Future<void> morePosts(int length) async {
Response response;
var dio = Dio();
response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/?offset=' + length.toString());
var posts = (response.data as List);
state = [...state, ...posts.map((post) => BlogPost.fromJson(post)).toList()];
}
}
Future<List<BlogPost>> getPosts() async {
Response response;
var dio = Dio();
response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/');
var posts = (response.data as List);
return posts.map((post) => BlogPost.fromJson(post)).toList();
}
我认为更好的方法是使用 AsyncValue
,但是,我找不到任何使用 API 的好的参考实现。
请最好创建另一个 class 以提供来自 Api 的数据并使用漂移包 查看我的屏幕我如何从数据库提供数据(漂移是 sqlite DB) 这是我的数据库 class 基于 sqlite(drift)
import 'dart:io';
import 'package:drift/native.dart';
import 'package:mobile_nsk/models/policy/driver.dart';
import 'package:mobile_nsk/models/policy/driver_converter.dart';
import 'package:mobile_nsk/models/policy/holders.dart';
import 'package:mobile_nsk/models/policy/holders_converter.dart';
import 'package:mobile_nsk/models/policy/vehicle.dart';
import 'package:mobile_nsk/models/policy/vehicle_converter.dart';
import 'package:path/path.dart' as p;
import 'package:drift/drift.dart';
import 'package:path_provider/path_provider.dart';
part 'database.g.dart';
LazyDatabase _openConnection()=> LazyDatabase(()async{
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'db.sqlite'));
return NativeDatabase(file,logStatements: true);
});
@DriftDatabase(tables: [Holders, Drivers, Vehicles])
class MyDatabase extends _$MyDatabase {
MyDatabase() : super(_openConnection());
// Для страхователя
Future<List<Holder>> getAllHolders() => select(holders).get();
Stream<List<Holder>> watchAllHolder() => select(holders).watch();
Future insertNewHolder(Holder holder) => into(holders).insert(holder, mode: InsertMode.insertOrReplace);
Future deleteHolder(Holder holder) => delete(holders).delete(holder);
Future<Holder> getHolderById(Holder holder)=> select(holders).getSingle();
Future insetData(Holder holder) => into(holders).insert(holder, mode: InsertMode.insertOrReplace);
Future updateHolder(Holder holder, int id, String phone) async
{
await update(holders)..where((tbl) => tbl.id.equals(id))..write(HoldersCompanion(phone: Value(phone)));
await into(holders).insert(holder, mode: InsertMode.insertOrReplace);
}
// Для Водителя
Future<List<Driver>> getAllDriver() => select(drivers).get();
Stream<List<Driver>> watchAllDriver() => select(drivers).watch();
Future insertNewDriver(Driver driver) => into(drivers).insert(driver, mode: InsertMode.insertOrReplace);
Future deleteDriver(Driver driver) => delete(drivers).delete(driver);
// Для транспорта
Future<List<Vehicle>> getAllVehicles() => select(vehicles).get();
Stream<List<Vehicle>> watchAllVehicle() => select(vehicles).watch();
Future insertNewVehicle(Vehicle vehicle) => into(vehicles).insert(vehicle, mode: InsertMode.insertOrReplace);
Future deleteVehicle(Vehicle vehicle) => delete(vehicles).delete(vehicle);
// всегда инкрементить версию схему если что то добавил/убрал/изменил/нахуевертил
@override
int get schemaVersion => 1;
}
这是我的支架模型(由 build_runner 生成)
import 'package:drift/drift.dart';
import 'package:json_annotation/json_annotation.dart' as j;
import 'package:mobile_nsk/database/database.dart';
import 'package:mobile_nsk/models/policy/holders_converter.dart';
@UseRowClass(Holder)
class Holders extends Table{
IntColumn get id => integer()();
TextColumn get firstName =>text()();
TextColumn get middleName => text()();
TextColumn get lastName => text()();
TextColumn get legalName => text()();
IntColumn get isIndividual => integer()();
TextColumn get iin => text()();
IntColumn get isResident => integer()();
TextColumn get phone => text()();
TextColumn get email => text()();
TextColumn get address => text()();
IntColumn get documentTypeId => integer()();
TextColumn get documentNumber => text()();
TextColumn get documentIssueDate => text()();
TextColumn get classType => text().named("class")();
TextColumn get birthDate => text()();
BoolColumn get isExperienced => boolean()();
BoolColumn get isPrivileged => boolean()();
TextColumn get holders =>
text().map(const HolderConverter()).nullable()();
@override
Set<Column> get primaryKey=> {id};
}
@j.JsonSerializable()
class Holder implements Insertable<Holder>{
final int id;
final String firstName;
final String middleName;
final String lastName;
final String legalName;
final int isIndividual;
final String iin;
final int isResident;
final String phone;
final String email;
final String address;
final int documentTypeId;
final String documentNumber;
final String documentIssueDate;
@j.JsonKey(name: "class")
final String classType;
final String birthDate;
final bool isExperienced;
final bool isPrivileged;
const Holder(this.id, this.firstName, this.middleName, this.lastName, this.legalName, this.isIndividual, this.iin, this.isResident, this.phone, this.email, this.address, this.documentTypeId, this.documentNumber, this.documentIssueDate, this.classType, this.birthDate, this.isExperienced, this.isPrivileged);
factory Holder.fromJson(Map<String, dynamic>json)=> Holder(
json['id'] as int,
json['firstName'] as String? ?? "",
json['middleName'] as String? ?? "",
json['lastName'] as String? ?? "",
json['legalName'] as String? ?? "",
json['isIndividual'] as int,
json['iin'] as String? ?? "",
json['isResident'] as int? ?? 0,
json['phone'] as String? ?? "",
json['email'] as String? ?? "",
json['address'] as String? ?? "",
json['documentTypeId'] as int? ?? 0,
json['documentNumber'] as String? ?? "",
json['documentIssueDate'] as String? ?? "",
json['class'] as String? ?? "",
json['birthDate'] as String? ?? "",
json['isExperienced'] as bool? ?? false,
json['isPrivileged'] as bool? ?? false,
);
Map<String, dynamic>toJson()=>{
'id': id,
'firstName':firstName,
'middleName': middleName,
'lastName': lastName,
'legalName': legalName,
'isIndividual': isIndividual,
'iin': iin,
'isResident': isResident,
'phone': phone,
'email': email,
'address': address,
'documentTypeId': documentTypeId,
'documentNumber': documentNumber,
'documentIssueDate': documentIssueDate,
'class': classType,
'birthDate': birthDate,
'isExperienced': isExperienced,
'isPrivileged': isPrivileged,
};
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
return HoldersCompanion(
id: Value(id),
firstName: Value(firstName),
middleName: Value(middleName),
lastName: Value(lastName),
legalName: Value(legalName),
isIndividual: Value(isIndividual),
iin: Value(iin),
isResident: Value(isResident),
phone: Value(phone),
email: Value(email),
address: Value(address),
documentTypeId: Value(documentTypeId),
documentNumber: Value(documentNumber),
documentIssueDate: Value(documentIssueDate),
classType: Value(classType),
birthDate: Value(birthDate),
isExperienced: Value(isExperienced),
isPrivileged: Value(isPrivileged)
).toColumns(nullToAbsent);
}
}
这是我从 api 到数据库
的代码插入 import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:mobile_nsk/database/database.dart';
import 'package:mobile_nsk/models/policy/holders.dart';
class HolderProvider {
String baseUrl = 'http://172.16.3.49:9096/api/v1';
Future<void> getHolder(
String iin,MyDatabase database
) async {
final response = await http.get(
Uri.parse(baseUrl + '/Customer/get_full_client?iin=$iin'),
headers: {'Content-Type': 'application/json'});
if (jsonDecode(response.body)['isExperienced'] != false) {
database.insertNewHolder(Holder.fromJson(jsonDecode(response.body)));
} else {
throw Exception();
}
}
}
这是一个使用 AsyncValue
的示例 - 它消除了 repository
让你的 service.dart 文件像这样:
final blogServiceProvider = Provider<BlogService>((ref) => BlogService());
class BlogService {
Future<AsyncValue<List<BlogPost>>> getBlogPost() async {
try {
var dio = Dio();
Response response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/');
var posts = (response.data as List);
List<BlogPost> list = posts.map<BlogPost>((post) => BlogPost.fromJson(post)).toList();
return AsyncData(list);
} catch (e) {
return AsyncError("Something went wrong");
}
}
}
你的供应商是这样的:
final blogNotifierProvider = StateNotifierProvider<BlogNotifier, AsyncValue<List<BlogPost>>>((ref){
BlogService _service = ref.read(blogServiceProvider);
return BlogNotifier(_service);
});
class BlogNotifier extends StateNotifier<AsyncValue<List<BlogPost>>> {
BlogNotifier(this._service) : super(AsyncLoading()) {
getPosts();
}
final BlogService _service;
void getPosts() async {
state = await _service.getBlogPost();
}
}
编辑:要将现有帖子与新帖子合并,试试这个:
class BlogService {
List<BlogPost> _posts = [];
Future<AsyncValue<List<BlogPost>>> getBlogPost() async {
try {
var dio = Dio();
Response response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/');
var posts = (response.data as List);
List<BlogPost> list = posts.map<BlogPost>((post) => BlogPost.fromJson(post)).toList();
_posts = list;
return AsyncData(list);
} catch (e) {
return AsyncError("Something went wrong");
}
}
Future<AsyncValue<List<BlogPost>>> morePosts() async {
try {
var dio = Dio();
Response response = await dio.get('https://wordpress-site.com/wp-json/wp/v2/posts/?offset=' + length.toString());
var posts = (response.data as List);
List<BlogPost> list = posts.map<BlogPost>((post) => BlogPost.fromJson(post)).toList();
_posts.addAll(list);
return AsyncData(_posts);
} catch (e) {
return AsyncError("Something went wrong");
}
}
}
通知者 class 将是:
class BlogNotifier extends StateNotifier<AsyncValue<List<BlogPost>>> {
BlogNotifier(this._service) : super(AsyncLoading()) {
getPosts();
}
final BlogService _service;
void getPosts() async {
state = await _service.getBlogPost();
}
void morePosts() async {
state = await _service.morePosts();
}
}