NCMBのFlutter SDKを使ってニュースアプリを作る（その3：ニュースの詳細表示とお気に入り登録）

NCMBでは公式SDKとしてSwift/Objective-C/Java/Unity/JavaScript SDKを用意しています。また、それ以外にもコミュニティSDKとして、非公式ながらFlutter/React Native/Google Apps Script/C#/Ruby/Python/PHPなど幅広い言語向けにSDKが開発されています。

今回はコミュニティSDKの一つ、Flutter SDKを使ってニュースアプリを作ってみます。前回は[ニュースの取得と、一覧表示までを実装しました](https://qiita.com/goofmint/items/2f0de85c4f59d1785473)。今回は詳細表示とお気に入り登録までの流れを解説します。

## 完成版のコード

作成したデモアプリのコードは[NCMBMania/flutter_news: Flutter SDKを使ったニュースアプリデモです。](https://github.com/NCMBMania/flutter_news)にアップロードしてあります。

## 記事の詳細表示

![localhost_53010_ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/e69c36a0-18c7-7295-c187-cdffcd8b6bed.png)


一覧画面でタップした際に、記事のデータはMyDetailPageへ送っています。そのため、記事表示についてはMyDetailPage側で表示するだけです。注意点としてはHTMLレンダリングをflutter_htmlで行っていることでしょう。表示対象は `widget.object` でアクセスできます。

```dart
@override
Widget build(BuildContext context) {
	return Scaffold(
			appBar: AppBar(
					title: Text(widget.object.get('title') as String),
					actions: <Widget>[
						IconButton(
							icon: Icon(favoriteIcon()),
							onPressed: () async {
								await favorite();
							},
						),
					]),
			body: Center(
					child: SingleChildScrollView(
							child: Html(data: widget.object.get('content') as String))));
}
```

### お気に入り登録（または削除）処理

お気に入りデータはFavoriteクラスに保存します。まず画面が表示されたタイミングで、お気に入り登録状態をチェックします。

Favoriteクラスのentryフィールドに該当するデータがあるか調べます。これがあればお気に入り登録済み、なければ未登録と判断します。fetchAllは条件にマッチする全データを返しますが、fetchは最初の1件だけを返します。

```dart
class _MyDetailPageState extends State<MyDetailPage> {
  bool favorited = false;
  NCMBObject? _favorite;

  @override
  void initState() {
    super.initState();
    checkFavorited();
  }

	Future<void> checkFavorited() async {
    setState(() {
      favorited = false;
    });
    var query = NCMBQuery('Favorite');
    query.equalTo('entry', widget.object);
    _favorite = await query.fetch();
    if (_favorite != null) {
      setState(() {
        favorited = true;
      });
    }
  }
}
```

### お気に入り登録処理

画面上部の星アイコンをタップすると、お気に入り登録処理 `favorite` が実行されます。この処理では、すでに登録済みか否かで呼び出す関数が変わります。

```dart
Future<void> favorite() async {
	if (favorited) {
		await removeFavorite();
	} else {
		await addFavorite();
	}
}
```

お気に入り登録処理である addFavorite は次のようになります。データを登録（または更新や削除）する際にはNCMBObjectを使います。また、データを安全に管理するためにACL（アクセスコントロール）を利用する際にはNCMBAclを使います。

今回は登録した本人だけが閲覧、更新（削除）できるACLを適用しています。

```dart
Future<void> addFavorite() async {
	var user = await NCMBUser.currentUser();
	var acl = NCMBAcl();
	acl
		..setPublicReadAccess(false)
		..setPublicWriteAccess(false)
		..setUserReadAccess(user!, true)
		..setUserWriteAccess(user, true);

	_favorite = NCMBObject('Favorite');
	_favorite!
		..set('entry', widget.object)
		..set('acl', acl);
	await _favorite!.save();
	setState(() {
		favorited = true;
	});
}
```

逆にお気に入りを削除する処理はremoveFavoriteになります。こちらはdeleteメソッドで削除できます。

```dart
Future<void> removeFavorite() async {
	await _favorite?.delete();
	setState(() {
		favorited = false;
	});
}
```

## お気に入り記事の一覧表示

お気に入り登録した記事だけを一覧表示する際には _MyHomePageState にて表示する記事を絞り込みます。getFavorites関数では、includeを使ってEntryクラスのデータも一緒に取得します。そして結果の中からentryフィールドのデータだけを一覧にすることで、一覧表示を更新できます。

```dart
getFavorites() async {
	await login();
	var favorite = NCMBQuery('Favorite');
	favorite
		..include('entry')
		..order('createDate');
	var favorites = await favorite.fetchAll();
	var ary = favorites.map((f) => f.get('entry')).toList();
	setState(() {
		listItem = ary;
	});
}
```

## まとめ

今回のニュースアプリでは、NCMBの以下の機能を利用しています。

- 会員管理
	- 匿名認証
- データストア
	- Feedクラス
		- データ登録
		- データ検索
	- Entryクラス
		- データ登録
		- データ検索
		- データ削除
- スクリプト
	- GET実行

NCMBには他にもプッシュ通知やファイルストアなど、多くの機能があります。Flutterアプリ開発時に役立ててください。

[mBaaSでサーバー開発不要！ | ニフクラ mobile backend](https://mbaas.nifcloud.com/)