NCMBのFlutter SDKを使って翻訳アプリを作る（その3：履歴画面の構築とデータの取得/削除処理）

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

今回はコミュニティSDKの一つ、Flutter SDKとDeepL APIを使って翻訳アプリを作ってみます。[前回は翻訳画面と翻訳処理について解説しました](https://qiita.com/goofmint/items/e92ce8a4617cd768ab27)ので、今回は翻訳履歴の取得と一覧表示について解説します。

[ncmb | Dart Package](https://pub.dev/packages/ncmb)

## 完成版のコード

作成したデモアプリのコードは[NCMBMania/flutter_translation_app: Flutter SDKとDeepL APIを組み合わせた翻訳アプリです](https://github.com/NCMBMania/flutter_translation_app)にアップロードしてあります。

## HistoryPageについて

HistoryPageは_HistoryPageStateを読み込んでいるだけです。

```dart
// 履歴画面のStatefulWidget
class HistoryPage extends StatefulWidget {
  const HistoryPage({Key? key}) : super(key: key);
  @override
  State<HistoryPage> createState() => _HistoryPageState();
}
```

## _HistoryPageStateについて

_HistoryPageStateではニフクラ mobile backendからデータを取得し、それをリストを使って一覧表示します。

```dart
class _HistoryPageState extends State<HistoryPage> {

}
```

### インスタンス変数について

_HistoryPageStateで用意しているインスタンス変数は次の通りです。

```dart
// 履歴のNCMBObjectが入る配列
var _histories = [];
```

### 初期化処理

`initState` でデータを取得します。

```dart
// 初期化処理
@override
void initState() {
	super.initState();
	// 履歴を取得する
	_getHistory();
}
```

### _getHistory関数について

`_getHistory` 関数ではニフクラ mobile backendからデータを取得します。この時はNCMBQueryを使います。引数はクラス名で、DBでいうテーブル名に相当します。

検索条件は様々に指定できますが、今回は件数以外の絞り込みは行っていません。

```dart
// 履歴を取得する処理
void _getHistory() async {
	// Translateクラスから10件取得
	final query = NCMBQuery('Translate');
	query.limit(10);
	// 検索実行
	final results = await query.fetchAll();
	// 検索結果を画面に反映
	setState(() {
		_histories = results;
	});
}
```

### 画面表示について

画面は以下のようになります。一覧をタップすると、該当するデータの翻訳結果をクリップボードへコピーする `_copyText` を呼び出します。ロングタップでは該当するデータを削除する `_deleteItem` を呼び出します。

一覧表示する際にはNCMBObjectのgetStringを使うと便利です。オプションとしてdefaultValueを指定すると、万一該当するフィールドがない（= nullになる）場合もdefaultValueを返してくれるので致命的エラーになりません。

```dart
// 画面を構築
@override
Widget build(BuildContext context) {
	return ListView.builder(
		itemBuilder: (BuildContext context, int index) {
			var item = _histories[index] as NCMBObject;
			return Container(
					decoration: const BoxDecoration(
						border: Border(
							bottom: BorderSide(color: Colors.black38),
						),
					),
					child: ListTile(
							title: Text(item.getString('original')),
							subtitle: Text(
									item.getString('translate', defaultValue: "翻訳がありません"),
									overflow: TextOverflow.ellipsis,
									maxLines: 2),
							onLongPress: () {
								_deleteItem(context, item);
							},
							onTap: () {
								_copyText(item);
							}));
		},
		itemCount: _histories.length,
	);
}
```

![Simulator Screen Shot - iPhone SE (3rd generation) - 2022-06-20 at 17.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/27ca574f-789b-6ce3-bfd8-99fd19fa78bb.png)


### タップした際の処理

一覧をタップした際には、翻訳結果をクリップボードへコピーします。この処理自体は翻訳画面と同じです。

```dart
// タップしたデータの翻訳結果をクリップボードに入れる処理
void _copyText(NCMBObject item) {
	Clipboard.setData(ClipboardData(text: item.getString('translate')));
}
```

### ロングタップした際の処理

ロングタップした際には、まず確認ダイアログを表示します。その結果、削除しますがタップされた場合には該当するNCMBObjectのdeleteメソッドを実行します。これだけでクラウドのデータ削除されます。

削除後は一覧を更新します。

```dart
// ロングタップしたデータを削除する処理
void _deleteItem(context, NCMBObject item) async {
	// ダイアログ表示
	final result = await showDialog(
		context: context,
		barrierDismissible: false,
		builder: (_) {
			return AlertDialog(
				title: const Text("削除の確認"),
				content: const Text("選択した翻訳を削除します"),
				actions: [
					TextButton(
						child: const Text("キャンセル"),
						onPressed: () =>
								{Navigator.of(context, rootNavigator: true).pop(false)},
					),
					TextButton(
						child: const Text("削除する"),
						onPressed: () =>
								{Navigator.of(context, rootNavigator: true).pop(true)},
					),
				],
			);
		},
	);
	// 結果の判定
	if (result) {
		// OKボタンを押されたらデータ削除
		await item.delete();
		// 履歴一覧を更新
		_getHistory();
	}
}
```

![Simulator Screen Shot - iPhone SE (3rd generation) - 2022-06-20 at 17.00.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/804e95e4-26a1-5376-eb08-4e40d7700f37.png)


## まとめ

これでDeepL APIとNCMBを使った翻訳アプリの完成です。NCMBでは他にも認証機能やファイルストア、プッシュ通知などの機能を提供しています。ぜひあなたのアプリ開発に活かしてください。

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