Flipper の導入

### Flipper

Androidで、デバッグする際、logcatを確認することは多いと思いますが、DBの中身だったりレイアウトのチェックなどは出来ません。
そこで、プラグインを導入することで、デバッグすることが可能な Flipper を紹介したいと思います。
Flipperは、Facebook製のデバッグツールです。
Androidからの通知をPCのデスクトップアプリにGUIツールです。

* [Flipper](https://fbflipper.com/)
* [Github](https://github.com/facebook/flipper)

### Flipper の導入

* Gradleに定義

```gradle:build.gradle.kts
    debugImplementation("com.facebook.flipper:flipper:0.104.0")
    debugImplementation("com.facebook.soloader:soloader:0.10.1")

    releaseImplementation("com.facebook.flipper:flipper-noop:0.104.0")

    // plugin
    debugImplementation("com.facebook.flipper:flipper-network-plugin:0.104.0")
```

* Applicationクラスに実装

```kotlin:MyApplication.kt
    override fun onCreate() {
        super.onCreate()

        SoLoader.init(context, false)

        if (BuildConfig.DEBUG) {
            if (FlipperUtils.shouldEnableFlipper(context)) {
                AndroidFlipperClient.getInstance(context).apply {
                    addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()))
                    addPlugin(DatabasesFlipperPlugin(context))
                    addPlugin(SharedPreferencesFlipperPlugin(context))
                    addPlugin(LeakCanary2FlipperPlugin())
                    start()
                }
            }
        }

    }
```

これだけで、デバッグ情報がPCのFlipperアプリで確認することが可能です。
ただし、プラグインを導入する場合、少し複雑になります。
Gradleの定義で、debugImplementationとなっているものは、デバッグ時だけ読み込まれます。
releaseImplementationは、リリース時に読み込まれれますが、noopとなっているため処理が実装されていないインターフェイスが呼び出されます。

flipper-network-pluginは、debugImplementationのみとなるので、リリース時はインターフェイスが呼び出されないため、ビルドエラーとなります。

そのため、デバッグとリリースで、処理を分ける必要があり、リリース時はプラグインを使わないようにしてあげる必要があります。

### プラグイン使用時

例として、Network Pluginを記載します。
まず、/app/src/debugと/app/src/releaseのフォルダーを用意します。

* /app/src/debug

debugImplementationで定義されているプラグインが使用できる。

```kotlin:FlipperNetwork.kt
object FlipperNetwork {

    private val networkFlipperPlugin = NetworkFlipperPlugin()

    fun createFlipper(context: Context) {
        SoLoader.init(context, false)

        if (BuildConfig.DEBUG) {
            if (FlipperUtils.shouldEnableFlipper(context)) {
                AndroidFlipperClient.getInstance(context).apply {
                    addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()))
                    addPlugin(DatabasesFlipperPlugin(context))
                    addPlugin(networkFlipperPlugin)
                    addPlugin(SharedPreferencesFlipperPlugin(context))
                    addPlugin(LeakCanary2FlipperPlugin())
                    start()
                }
            }
        }
    }

    fun getOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor(FlipperOkhttpInterceptor(networkFlipperPlugin))
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
           .build()
    }
```

* /app/src/release

プラグインは、呼び出せないため、空の呼び出しを作成する。

```kotlin:FlipperNetwork.kt
object FlipperNetwork {

    fun createFlipper(context: Context) {

    }

    fun getOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
           .build()
    }
```

* Applicationクラスに実装

これを実装することで、デバック時はFlipperを使用して、リリース時はFlipperを使用しない実装が可能になります。

```kotlin:MyApplication.kt
    override fun onCreate() {
        super.onCreate()

        FlipperNetwork.createFlipper(this)
    }
```