使用无头 Oracle Content Management 在 Flutter 中构建映像库
简介
Flutter 是 Google 提供的开源框架,用于从单个代码库构建美丽、原生编译的多平台应用。Flutter 代码编译为 ARM 或 Intel 机器码以及 JavaScript,可在任何设备上实现快速性能。Flutter 可以是构建使用 Oracle Content Management 内容的应用程序的强大工具。借助合适的内容模型,您可以快速构建 Flutter UI 来组成典型的库。
在本教程中,我们将利用 Oracle Content Management 作为无头 CMS 在 Flutter 中构建一个简单的库。GitHub 上提供了此 Flutter 示例。
本教程包含三个步骤:
先决条件
继续本教程之前,我们建议您先阅读以下信息:
要遵循本教程,您需要:
- Oracle Content Management 订阅
- 具有内容管理员角色的 Oracle Content Management 账户
- 具有节点版本 10 或更高版本的 Windows 或 Mac 计算机
我们正在建设
我们的图像画廊将包括几个屏幕的食品和饮料在咖啡店。
类别是分类的子节点,可以组织成层次结构。对于图像库,我们希望显示所有可用的类别,而不考虑组织。为此,我们首先需要查找可用的分类,使用 REST API 资源 GET /published/api/v1.1/taxonomies。
接下来,我们需要获取每个分类的类别集。这是使用 REST API GET /published/api/v1.1/taxonomies/{id}/categories 完成的。
要构建类别预览(例如,Bagels),我们需要获得前四个图像的图像数量和 URL 的计数。
我们要求在类别中查找已发布资产,通过查询字符串指定类别标准,如下所示:
"(taxonomies.categories.nodes.id eq 892CD6BC4F654249A00CB7942EE8C773)"
注意:除了发布要查看的数字资产之外,还需要将分类发布到渠道。
要继续,您需要对 Oracle Content Management 进行有效订阅,并使用内容管理员角色登录。
任务 1:准备 Oracle Content Management
本教程基于您已创建资产存储库并且当前具有空内容模型(即未创建内容类型)的假设。
如果您还没有 Oracle Content Management 实例,请参阅快速启动以了解如何注册 Oracle Cloud、预配 Oracle Content Management 实例以及将 Oracle Content Management 配置为无头 CMS。
对于本教程,您将需要通过两种方式之一创建内容模型。有一个可下载的资产包可用于为空存储库填写内容类型和关联内容,您也可以创建自己的内容模型和内容。
要准备 Oracle Content Management,请执行以下操作:
创建渠道和资产存储库
首先需要在 Oracle Content Management 中创建渠道和资产存储库,以便发布内容。
要在 Oracle Content Management 中创建渠道和资产存储库,请执行以下操作:
以管理员身份登录 Oracle Content Management Web 界面。
在左侧导航菜单中选择内容,然后从页眉的选择列表中选择发布渠道。
在右上角,单击创建以创建新通道。为本教程的目的命名渠道“OCEImageGalleryChannel”,并将访问权限保持为公开。单击保存以创建通道。
在左侧导航菜单中选择内容,然后从页眉的选择列表中选择资料档案库。
在右上角,单击创建以创建新的资产存储库。为此教程的目的,将资产存储库命名为“OCEImageGalleryRepository”。
在发布通道字段中,选择 OCEImageGalleryChannel 以向 Oracle Content Management 指明 OCEImageGalleryRepository 资料档案库中的内容可以发布到 OCEImageGalleryChannel 通道。完成后单击保存。
导入 Oracle Content Management 示例资产包
您可以下载预配置的 Oracle Content Management 示例资产包,其中包含此教程所需的所有内容类型和资产。
您可以从 Oracle Content Management 示例资产包上载本教程中使用的内容的副本。这样,您可以试验内容类型并修改内容。您可以下载资产包归档文件 OCESamplesAssetPack.zip,然后将其提取到您选择的目录中:
从 Oracle Content Management 下载页下载 Oracle Content Management 示例资产包 (OCESamplesAssetPack.zip)。将下载的 zip 文件解压缩到计算机上的某个位置。提取后,此位置将包括一个名为 OCEImageGallery_data.zip 的文件。
以管理员身份登录 Oracle Content Management Web 界面。
在左侧导航菜单中选择内容,然后从页眉的选择列表中选择资料档案库。现在选择 OCEImageGalleryRepository,然后单击顶部操作栏中的导入内容按钮。
将 OCEImageGallery_data.zip 从本地计算机上载到文档文件夹。
上载后,选择 OCEImageGallery_data.zip 并单击确定将内容导入到资产存储库中。
成功导入内容后,导航到资产页并打开 OCEImageGalleryRepository 系统信息库。您将看到所有相关图像和内容项现在已添加到资产存储库中。
单击左上方的全选,然后单击发布将所有导入的资产添加到您之前创建的发布渠道 OCEImageGalleryChannel。
在发布之前,您需要验证所有资产。首先将 OCEImageGalleryChannel 添加为所选通道,然后单击验证按钮。
验证资产后,可以通过单击右上角的发布按钮将所有资产发布到选定渠道。
完成此操作后,您可以在资产页上看到所有资产都已发布。(您可以通过资产名称上方的图标来判断。)
导入 Oracle Content Management 示例资产包后,您可以开始在 Flutter 中构建映像库。
上载您自己的映像资产
对于本教程,我们使用名为“OCEImageGalleryRepository”的资产存储库来构建库站点的主页。此主页包含标题“Image Gallery(图像库)”以及包含图像资产的图像集合专辑。
要将图像资产添加到库资产存储库,请执行以下操作:
登录到 Oracle Content Management Web 界面。
单击左侧导航菜单中的资产。
打开 OCEImageGalleryRepository 系统信息库。
单击页面右上角的添加,将图像资产添加到库资产存储库。
从本地计算机上载您自己的新资产,或者选择已在 Oracle Content Management 中的现有资产。
创建分类并将它们链接到图像资产
您需要在 Oracle Content Management 中创建分类,然后将类别分配给存储库中的资产。
要在 Oracle Content Management 中创建分类,请执行以下操作:
以管理员身份登录 Oracle Content Management Web 界面。
在左侧导航菜单中选择内容,然后从页眉的选择列表中选择分类。
在右上角,单击创建以创建新分类。为此教程的目的,将渠道命名为“OCEImageGalleryTaxonomy”。
单击创建。
现在,通过添加类别来构建分类。单击添加类别。
将父类别项命名为“Food”,然后添加以下子类别:
- 早餐
- 甜点
- 饮料
- 三明治
单击屏幕右上方的完成。
在“分类”页上,选择 OCEImageGalleryTaxonomy 分类并单击操作栏中的提升以使其可用于资产存储库。
接下来,编辑 OCEImageGalleryRepository 系统信息库以为该系统信息库启用 OCEImageGalleryTaxonomy 分类:
以管理员身份登录 Oracle Content Management Web 界面。
在左侧导航菜单中选择内容,然后从页眉的选择列表中选择资料档案库。
选择并编辑 OCEImageGalleryRepository 系统信息库。
在分类字段中,选择 OCEImageGalleryTaxonomy,以便您可以将该分类中的类别分配给 OCEImageGalleryRepository 存储库中的资产。
单击保存。
然后,将分类类别分配给 OCEImageGalleryRepository 存储库中的每个图像资产:
登录到 Oracle Content Management Web 界面。
单击左侧导航菜单中的资产。
打开 OCEImageGalleryRepository 系统信息库。
选择一个或多个图像资产,单击操作栏中的更多,然后从菜单中选择类别。
在“类别”面板中,单击添加类别。在搜索栏中搜索类别名称,或者从分类层次结构中选择类别,然后单击添加以分配选定的类别。您可以将多个类别分配给一个资产。
将分类分配给所有映像资产后,选择存储库中的所有资产并将其发布到 OCEImageGalleryChannel 通道。
任务 2:在 Flutter 中构建图像库
要在 Flutter 应用程序中使用 Oracle Content Management 内容,可以使用 Flutter 库示例,该示例可作为 GitHub 上的开源资料档案库使用。
注意:请记住,使用 Flutter 示例是可选的,我们将在本教程中使用它来帮助您快速入门。您还可以构建自己的 Flutter 应用程序。
在 Flutter 中构建图像库由以下步骤组成:
安装 Flutter
要开始使用 Flutter,您需要做的第一件事是设置您的环境。您可以在Flutter 网站找到设置它的说明。使用与操作系统相对应的选项。下面是安装步骤的摘要:
- 获取 Flutter SDK。
- 更新路径环境变量。
- 运行
flutter doctor
。 - 按照Flutter 网站中列出的步骤安装您选择的编辑器。
- 为 Android Studio、IntelliJ、VS 代码或 Emacs 添加编辑器插件。说明指定如何在编辑器中安装 Flutter 和 Dart 插件。
- 修改 android.properties 文件中的值以引用相应的位置, sdk 和 kotlin 版本。您可能需要修改相应版本的 android.gradle 文件中的值。
克隆样例资料档案库并安装相关性
Flutter 库样例在 GitHub 上作为开源系统信息库提供。
首先需要将示例从 GitHub 克隆到本地计算机,并将目录更改为系统信息库根:
git clone https://github.com/oracle-samples/oce-flutter-gallery-sample.git
cd oce-flutter-gallery-sample
从 Android Studio 或您选择的任何其他编辑器打开项目。要获取项目中使用的所有软件包,请单击获取软件包按钮。
配置 Flutter 应用程序
在此 Flutter 库样例中,您需要配置一些信息,以便 REST API 请求可以使用正确的渠道令牌定位正确的实例 URL 和 API 版本。lib/config/oce.dart 中定义的这些值由 lib/networking/content.dart 中定义的函数使用,用于为 REST API 建立端点。
您可以在 lib/config/oce.dart 中看到以下信息:
const Map<String, String> config = <String, String>{
'serverUrl': 'https://samples.mycontentdemo.com',
'apiVersion': 'v1.1',
'channelToken': 'e0b6421e73454818948de7b1eaddb091'
};
更改每个键 - 值对以反映您的实例 URL、要定位的 API 版本以及与发布渠道关联的渠道标记。本教程的渠道为 OCEImageGalleryChannel。
使用 Oracle Content Management REST API 提取内容
通过 REST API for Content Delivery,可访问 Oracle Content Management 中发布的资产。已发布的资产包括内容项和数字资产,以及其重现。现在,我们可以利用 Oracle Content Management REST API 提取内容,以便将其显示在图像库 Flutter 应用程序中。
lib/networking/content.dart 文件使用 REST API 连接到 oce.dart 文件中指定的服务器并返回其响应的方法。
//Utility method to build up the URL for published content.
String _getPublishedContentServerURL() {
final String? serverUrl = data['serverUrl'] as String?;
final String? apiVersion = data['apiVersion'] as String?;
return '$serverUrl/content/published/api/$apiVersion/';
}
// Adds the channel token to the URL
String _addChannelToURL(String currUrl) {
final String? channelToken = data['channelToken'] as String?;
return '$currUrl?channelToken=$channelToken';
}
//Make an http get call and return the response if successful
Future<dynamic> _get(String url) async {
dynamic responseJson;
try {
final Response response = await get(Uri.parse(url));
responseJson = _returnResponse(response);
} on SocketException {
throw FetchDataException(kConnectionError);
}
return responseJson;
}
//Return the json decoded response body if response status is successful
dynamic _returnResponse(Response response) {
switch (response.statusCode) {
case 200:
final Map<String, dynamic>? responseJson =
json.decode(response.body.toString()) as Map<String, dynamic>?;
return responseJson;
case 400:
throw BadRequestException(response.body.toString());
case 401:
case 403:
throw UnauthorizedException(response.body.toString());
case 500:
default:
throw FetchDataException('StatusCode : ${response.statusCode}');
}
}
为了呈现图像,content.dart 还提供了帮助程序方法来检索资产的各种重现。
String getMediumRenditionUrl(Map<String, String> args) {
final String itemId = args['id'];
if (itemId == null) return null;
String url = _getPublishedContentServerURL();
url = '${url}assets/$itemId/Medium';
// add the channel token to the URL
url = _addChannelToURL(url);
url = '$url&format=jpg&&type=responsiveimage';
return url;
}
String getRenditionURL(Map<String, String> args) {
final String itemId = args['id'];
if (itemId == null) return null;
String url = _getPublishedContentServerURL();
url = '${url}assets/$itemId/native';
// add the channel token to the URL
url = _addChannelToURL(url);
return url;
}
lib/networking/services.dart 文件包含用于获取应用程序数据的所有代码。
主页数据
主页需要多个数据调用才能获取其所有数据:
- 首先,我们为 oce.dart 中指定的渠道加载分类。
- 对于每个分类,我们都会获得该分类中的所有类别。
- 对于每个类别,我们在该类别中获得四个内容项。
- 对于其中的每个项目,我们提取其重现 URL。
打开 lib/networking/services.dart 并找到下面的函数,这有助于获取主页的所有数据。
fetchTaxonomies() 与 fetchCategories() 函数一起获取所有分类中的所有类别。然后调用 fetchItemsForCategory 函数将四个类别项添加到每个类别。最后,调用 retrieveThumbnailURL 获取缩略图 URL。
// Fetch the taxonomies for the channel
Future<List<String>> fetchTaxonomies() async {
final Content content = Content();
try {
dynamic data = await content.getTaxonomies();
dynamic taxonomies = data['items'];
List<String> idArray = [];
for (var taxonomy in taxonomies) {
idArray.add(taxonomy['id']);
}
return idArray;
} catch (exception) {
rethrow;
}
}
// Fetch the categories for the specified taxonomyId.
Future<List<dynamic>> fetchCategories(taxonomyId) async {
final Content content = Content();
dynamic data = await content.queryTaxonomyCategories({
'id': '$taxonomyId',
});
return data['items'];
}
// Fetch the items that belong to the specified category
Future<dynamic> fetchItemsForCategory(String categoryId, bool limit) async {
final Content content = Content();
dynamic data = await content.queryItems({
'q': '(taxonomies.categories.nodes.id eq "$categoryId")',
'fields': 'all',
'expand': 'all',
'limit': limit ? '4' : '100',
'totalResults': 'true',
});
return data;
}
// Retrieve the thumbnail URL for the item specified.
Future<String> retrieveThumbnailURL(identifier) async {
final Content content = Content();
dynamic data = await content.getItem({
'id': identifier,
'fields': 'all',
'expand': 'all',
});
String url = data['fields']['renditions'][1]['formats'][0]['links'][0]['href'];
return url;
}
图像网格页
图像网格页面接收类别 ID,需要多次数据调用才能获取其所有数据:
- 获取指定类别的所有项。
- 对于每项,获取其重现 URL。
打开 lib/networking/services.dart 并找到下面的函数,该函数由 image_grid.dart 中的 fetchData 函数使用。
Future<dynamic> fetchItemsForCategory(String categoryId, bool limit) async {
final Content content = Content();
dynamic data = await content.queryItems({
'q': '(taxonomies.categories.nodes.id eq "$categoryId")',
'fields': 'all',
'expand': 'all',
'limit': limit ? '4' : '100',
'totalResults': 'true',
});
return data;
}
它调用 fetchItemsForCategory(如主页),但没有限制,因此将返回所有项,而不仅仅是四个项。
现在我们有数据查询,我们可以在 Flutter 组件中呈现响应。
Flutter 组件
库应用程序将每个页面分解为多个较小的组件。
接下来的几节概述了 Flutter 如何在我们的每个组件中呈现我们的应用程序:
HomePage 组件
主页包含分类的类别列表,其中预览该类别中的四个项。它由位于 lib/screens/home_page.dart 的 HomePage 组件呈现。组件使用 services.dart 文件中定义的函数获取数据。
Future<void> fetchData() async {
final Services services = Services();
try {
List<String> taxonomyIdArray = await services.fetchTaxonomies();
// For each taxonomy, fetch the categories and append them to an array
for (var taxonomyId in taxonomyIdArray) {
List<dynamic> data = await services.fetchCategories(taxonomyId);
for (var categoryData in data) {
categories.add(CategoryListItemModel.fromJson(categoryData));
}
setState(() {
categories = categories;
});
}
} catch (exception) {
setState(() => this.exception = exception.toString());
print(exception.toString());
}
}
此文件还使用位于 lib/components/card_grid.dart 的组件在网格中呈现图像。
ImageGrid 组件
ImageGridPage 组件显示类别中的项。它由位于 lib/screens/image_grid.dart 的 ImageGrid 组件呈现。
该组件调用并从 services.dart 文件获取数据。
Future<void> fetchData() async {
final Services services = Services();
String categoryId = widget.category.id;
try {
dynamic categoryItems =
await services.fetchItemsForCategory(categoryId, false);
items = categoryItems['items'];
setState(() {
dataFetched = true;
});
} catch (exception) {
setState(() {
this.exception = exception.toString();
});
print(exception.toString());
}
}
ImagePager 组件
位于 lib/screens/image_pager.dart 的 ImagePager 组件以滑动寻呼机形式显示项目。
任务 3:准备应用程序以进行部署
现在我们已经构建了 Flutter 映像库网站,我们需要将其部署在仿真器或设备上,以便我们可以在应用正式投入使用之前调试任何问题并预览应用。
按照Flutter 网站上的说明,让您的编辑器运行应用程序。
- 如果您使用 Android Studio 作为编辑器,请找到 Android Studio 主工具栏。
- 在目标选择器中,选择用于运行应用程序的 Android 设备。如果未列出任何可用项,请选择“Tools(工具)”>“Android”>“AVD Manager(AVD 管理器)”,并在其中创建一个。有关详细信息,请参阅管理 AVD。
- 单击工具栏中的“运行”图标,或者调用菜单项“运行”>“运行”。
结论
在本教程中,我们在 Flutter 中创建了一个库站点,可以在 GitHub 上找到该站点。此站点使用 Oracle Content Management 作为无头 CMS。在为图库站点教程设置和配置 Oracle Content Management 的已发布内容渠道后,我们安装并运行 Flutter 站点以提取所需内容并构建站点。
有关 Flutter 的更多信息,请访问 Flutter 网站。
在文档中了解重要的 Oracle Content Management 概念。
您可以在 Oracle 帮助中心的 Oracle Content Management 抽样页上找到更多类似示例。
使用无头 Oracle Content Management 在 Flutter 中构建映像库
F55470-01
2022 年 3 月
Copyright © 2021, 2022, Oracle and/or its affiliates.
第一作者:Oracle Corporation