Flutterで、Nifty mbaasのデータストアを読み書きする

※Androidのみ

# 1. Android用SDKをダウンロード

- https://mbaas.nifcloud.com/doc/current/introduction/sdkdownload_android.html
- ここの指示通りに、libs以下に放り込む
- どうもFlutterのAndroidStudioがこれ以降Javaのソースコードを編集するとエラーになる場合があるので、androidのプロジェクトだけUnloadしておく
    - Flutterプロジェクトで、プロジェクトビューのandroidディレクトリを右クリック→`Load/Unload Modules...`から設定できる

<img width="541" alt="スクリーンショット 2019-06-08 10.45.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213719/3d715838-076b-e6c2-7ee5-865de7768844.png">

# 2. Androidプラットフォーム用のコードを実装

- #1でAndroidプロジェクトをUnloadしたので、Androidプロジェクトを別にAndroidStudioで開いて編集する
- ネイティブ側とは、MethodChannelという機能を使ってやり取りできる
- https://flutter.dev/docs/development/platform-integration/platform-channels
- 上記を参考に、MainActivityに下記のコードを書いていく

```java
        new MethodChannel(getFlutterView(), "com.example/kakikomi").setMethodCallHandler(
                (methodCall, result) -> {
                    NCMBObject hist = new NCMBObject("History");
                    try {
                        Integer id = methodCall.argument("id");
                        hist.put("type", methodCall.method);
                        hist.put("time", (String) methodCall.argument("time"));
                        hist.put("id", id == null ? -1 : id);
                        hist.put("name", (String) methodCall.argument("name"));
                    } catch (NCMBException e) {
                        e.printStackTrace();
                    }
                    hist.saveInBackground(e -> {
                        if (e != null) {
                            result.error("FAILED", e.getMessage(), null);
                        } else {
                            result.success(null);
                        }
                    });
                }
        );

        new MethodChannel(getFlutterView(), "com.example/yomikomi").setMethodCallHandler(
                (methodCall, result) -> {
                    if ("getAll".equals(methodCall.method)) {
                        NCMBQuery<NCMBObject> query = new NCMBQuery<>("EmployeeList");
                        query.findInBackground((list, e) -> {
                            if (e != null) {
                                result.error("FAILED", e.getMessage(), null);
                            } else {
                                ArrayList<HashMap<String, Object>> employees = new ArrayList<>();
                                for (NCMBObject obj : list) {
                                    HashMap<String, Object> map = new HashMap<>();
                                    map.put("id", obj.getInt("id"));
                                    map.put("name", obj.getString("name"));
                                    employees.add(map);
                                }
                                result.success(employees);
                            }
                        });
                    } else {
                        result.error("UNAVAILABLE", "Not available method: " + methodCall.method, null);
                    }
                });
```

- 上記を呼び出すDartコードを、Flutter側に書く

```dart
static const kakikomiApi = const MethodChannel('com.example/kakikomi');
static const yomikomiApi = const MethodChannel('com.example/yomikomi');
await kakikomiApi.invokeMethod("start", <String, dynamic>{
  'id': id,
  'name': name,
  'time': DateFormat('yyyy/MM/dd HH:mm:ss').format(DateTime.now()),
});

final value = await yomikomiApi.invokeMethod("getAll");
List<Entity> list = [];
for (var e in value) {
  list.add(Entity(id: e["id"], name: e["name"]));
}
```

- invokeMethodは`List<dynamic>`で値を返してくるので、読み込むときはちょっと注意
- Java側でEntityクラスを作って渡してみたが、どうも独自型は駄目っぽい挙動だったので、HashMap<String, Object>などでFlutter側に渡した