跳至主要内容

连接您的数据源

模板的 Dart Frog API 充当您的 CMS 和客户端应用程序之间的中介,将您的内容组织成 区块,这些区块构成了应用程序中内容组织的基础。

如果您不打算编写自定义代码来支持来自您的 CMS 的必要区块组织端点,您应该创建和部署一个使用 NewsDataSource 接口来收集和转换数据的 API。

您的 NewsDataSource 实现由 api/routes 目录中布局的路由处理程序调用。然后,数据源从您的 CMS 请求数据,并将其组织成客户端预期的基于区块的数据,然后将其返回给路由处理程序,以服务于您的客户端应用程序。有关使用您的数据源的 Dart Frog 服务器的结构和功能的更多信息,请参阅 Dart Frog 文档

NewsDataSource 类(api/lib/src/data/news_data_source.dart)提供了一个您的数据源必须实现的接口。您可以随意删除提供您不打算在客户端应用程序中使用的数据的方法,或者添加方法来提供您打算添加到应用程序的功能的数据。

创建新的数据源

首先,定义一个实现 NewsDataSource 的新类

class YourCustomDataSource implements NewsDataSource

您的数据源应具有与您的 CMS 交互的方式,例如 HTTPDio 客户端,如果您的不同风格(例如 developmentproduction)有不同的 CMS URL,您可能需要创建单独的命名构造函数。

实现您的数据源

创建数据源类后,实现 NewsDataSource 中定义的方法

/// {@template news_data_source}
/// An interface for a news content data source.
/// {@endtemplate}
abstract class NewsDataSource {
/// {@macro news_data_source}
const NewsDataSource();

/// Returns a news [Article] for the provided article [id].
///
/// In addition, the contents can be paginated by supplying
/// [limit] and [offset].
///
/// * [limit] - The number of content blocks to return.
/// * [offset] - The (zero-based) offset of the first item
/// in the collection to return.
Future<Article?> getArticle({
required String id,
int limit = 20,
int offset = 0,
});
/// Returns a list of current popular topics.
Future<List<String>> getPopularTopics();
/// Returns a list of current relevant topics
/// based on the provided [term].
Future<List<String>> getRelevantTopics({required String term});
/// Returns a list of current popular article blocks.
Future<List<NewsBlock>> getPopularArticles();
/// Returns a list of relevant article blocks
/// based on the provided [term].
Future<List<NewsBlock>> getRelevantArticles({required String term});
/// Returns [RelatedArticles] for the provided article [id].
///
/// In addition, the contents can be paginated by supplying
/// [limit] and [offset].
///
/// * [limit] - The number of content blocks to return.
/// * [offset] - The (zero-based) offset of the first item
/// in the collection to return.
Future<RelatedArticles> getRelatedArticles({
required String id,
int limit = 20,
int offset = 0,
});
/// Returns a news [Feed] for the provided [category].
/// By default [Category.top] is used.
///
/// In addition, the feed can be paginated by supplying
/// [limit] and [offset].
///
/// * [limit] - The number of results to return.
/// * [offset] - The (zero-based) offset of the first item
/// in the collection to return.
Future<Feed> getFeed({
Category category = Category.top,
int limit = 20,
int offset = 0,
});

/// Returns a list of all available news categories.
Future<List<Category>> getCategories();
}

例如,getArticle() 的实现可能如下所示


Future<Article?> getArticle({
required String id,
int limit = 20,
int offset = 0,
bool preview = false,
}) async {
final uri = Uri.parse('$YOUR_CMS_BASE_URL/posts/$id');
final response = await httpClient.get(uri);
if (response.statusCode != HttpStatus.ok) {
throw YourAppApiFailureException(
body: response.body,
statusCode: response.statusCode,
);
}
final responseJson = response.jsonMap();
if (responseJson.isNotFound) return null;
final post = Post.fromJson(responseJson);
final article = post.toArticle();
return article;
}

上面的示例引用了模板中未包含的类 Post

class Post {
const Post({
required this.id,
required this.date,
required this.link,
required this.title,
required this.content,
required this.author,
required this.image,
required this.category,
});

final int id;
final DateTime date;
final String link;
final String title;
final String content;
final Author author;
final String image;
final PostCategory category;
}

由于您的 CMS 大概不会以 Article 类使用的基于区块的格式响应数据,您可能需要定义类似 Post 的类,以反映您的 CMS 返回的数据类型和格式。

您可以使用像 json_serializable 这样的包来生成代码,以从您的 CMS 返回的 JSON 创建 Post 对象(请参阅 JSON 和序列化 - Flutter 文档)。

然后,您可以 添加一个扩展方法,例如 toArticle(),在您的 Post 类上,该方法使用来自 Post 对象的相关数据,并创建并返回一个 Article 对象,该对象将服务于您的客户端应用程序。

当实现任何数据源方法时,可以重复这种 JSON -> 中间对象 -> API 模型的结构,该方法接收来自您的 CMS 的数据,该数据与预期该方法返回的数据不同。

注入您的数据源

创建数据源后,通过 Dart Frog 中间件 将其注入到您的 API 路由处理程序中。

首先,实例化您的数据源

final yourCustomDataSource = YourCustomDataSource();

然后,通过中间件将其作为 NewsDataSource 注入

handler.use(provider<NewsDataSource>((_) => yourCustomDataSource));

由于模板已经包含 NewsDataSource 依赖注入,您可以简单地实例化您的数据源,然后将 inMemoryNewsDataSource 替换为 yourCustomDataSource