ActiveAndroid => ReActiveAndroid 移行

アプリをリリースしようとしてtargetSdkVersionを26にするとActiveAndroidが動かない事態になりました。
どうやらメンテナンスされてないためまともに動かないご様子。
https://www.tsurutan.com/entry/2018/10/08/Migration_ActiveAndroid_to_Room
https://qiita.com/pside/items/03e6256b404c75f5974b#activeandroid%E3%81%AE%E7%A7%BB%E8%A1%8C%E3%83%91%E3%82%B9%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AEreactiveandroid

既存の記述も結構な量があり、完全に新規のライブラリに移行するのがきつかったので結構な互換性がある
ReActiveAndroidに移行
（新規だともっと選択の余地があります。Roomとか…）

下記そのときの対応メモです
需要があるかどうかは全くわかりませんが同じことで困ってる人の助けになれば…

#対応
下記ドキュメントの通りに対応する
https://imangazalievm.gitbooks.io/reactiveandroid/migration-from-activeandroid.html

DB名とテーブル名はそれぞれ`DbName`、`TableName`に書き換えてます。

- `build.gradle`に

```
implementation 'com.reactiveandroid:reactiveandroid:1.4.3'
implementation 'android.arch.persistence:db:1.1.1'
```
を追記。

- `DbName.java`を作成、`@Database(name = "DbName", version = 1)`と下記マイグレーションメソッドを記述。


```DbName.java
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        // Since we didn't alter the table, there's nothing else to do here.
    }
};
```
- App.javaの初期化部分から下記の形で呼び出す

```App.java
        DatabaseConfig appDatabaseConfig = new DatabaseConfig.Builder(DbName.class)
                .addMigrations(DbName.MIGRATION_1_2)
                .build();

        ReActiveAndroid.init(new ReActiveConfig.Builder(this)
                .addDatabaseConfigs(appDatabaseConfig)
                .build());
```

- ソースコード内の`activeandroid`のimport文を全て消して`reactiveandroid`の方をimportする。ディレクトリ構成は変わってないので、`activeandroid`の部分を`reactiveandroid`に置き換えでいけるはず。
- プライマリキーに`@PrimaryKey(name = "id")`を追記する。
- 各ModelクラスのTableのアノテーションを`@Table( name = "tableName", database = DbName.class)`に変更
- 下記の通りメソッド呼び出しの構文を変更
    - `new Select()`を`Select`に変更
    - `executeSingle`を`fetchSingle`に変更
    - `execute`を`fetch`に変更

こんな感じ⬇︎

```java
- new Select().from(TableName.class).where("Id = %d".format(id)).executeSingle[TableName]();
+ Select.from(TableName.class).where("Id = %d".format(id)).fetchSingle();
```

- `exist()`にあたるメソッドが見当たらないので、`count() > 0`で判定する。
（パフォーマンスに影響出るかもなので確認。出そうだったらlimitをつける）
- ActiveAndroidで標準装備されてたgetId()とかのgetter/setterはReActiveAndroidでは存在しないので、必要なら自分で追記する
- transactionの記述を変更

```java
- ActiveAndroid.beginTransaction();
- ActiveAndroid.setTransactionSuccessful();
- ActiveAndroid.endTransaction();

+ ReActiveAndroid.getDatabase(DbName.class).beginTransaction();
+ ReActiveAndroid.getDatabase(DbName.class).getWritableDatabase().setTransactionSuccessful();
+ ReActiveAndroid.getDatabase(DbName.class).endTransaction();
```

ここまでやったら動くはず…


#引っかかったところメモ
上記手順通りにやったら出ないはずです。

##Please provide a Migration
```
Please provide a Migration in the builder or call disableMigrationsChecking in the builder in which case ReActiveAndroid will re-create all of the tables.
```
マイグレーション処理を書き忘れてたのが原因
＞上記手順の通りにマイグレーションメソッドを追加、呼び出ししたら解消

##SupportSQLiteDatabaseが解決されない
https://mvnrepository.com/artifact/android.arch.persistence/db
でバージョンを確認、

```
implementation 'android.arch.persistence.db:1.1.1'
```
をgradleに追加
＞`Error:Failed to resolve: android.arch.persistence.db:1.1.1:`
のエラー。
＞http://fengwanxingzhou.coding.me/Android%E9%94%99%E8%AF%AF/
パッケージ名の指定が間違ってるっぽい。
`android.arch.persistence:db:1.1.1`にしたら通った。

##Couldn't read row 0, col -1 from CursorWindow
```
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
```
ActiveAndroidではCursorを使わず記述できるのでどっかの内部処理で使ってるはず。
＞エラー箇所（`Select`）の内部処理を見てもcursorを使ってるところが見当たらない…
＞`fetchSingle`の内部（Tableの定義を持ってきているところ）で使われてた。
＞ここにブレークポイントを貼ってみると、`idName`が`"_id"`のカラムを持ってこようとしていた。
テンプレをそのまま持ってきて`@PrimaryKey(name = "_id")`としたのが原因。（本当のカラム名は`Id`）
なので

```TableName.java
- @PrimaryKey(name = "_id")
+ @PrimaryKey(name = "Id")
```
と修正して解消。