DaggerHiltのAndroidEntryPointのCustomViewのInjectのタイミングメモ

以下のような場合に問題ないのかが気になっていました。 これ、クラッシュしそうですよね？？

```kotlin
  @Inject lateinit var dep: Dep
  val value = dep.value
```

```kotlin
class Dep @Inject constructor() {
  val value = "aaaa"
}

@AndroidEntryPoint
class CustomView @JvmOverloads constructor(
  context: Context,
  attrs: AttributeSet? = null,
  defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
  @Inject lateinit var dep: Dep
  val value = dep.value
}
```

これは以下のようなコードを生成し、CustomViewが継承するようになります。つまりコンストラクタ内でinjectされます。

```java
public abstract class Hilt_CustomView extends FrameLayout implements GeneratedComponentManagerHolder {
  private ViewComponentManager componentManager;

  private boolean injected;

  Hilt_CustomView(Context context) {
    super(context);
    inject();
  }

  Hilt_CustomView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    inject();
  }

  Hilt_CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    inject();
  }

  @TargetApi(21)
  Hilt_CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
      int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    inject();
  }
...
```

CustomViewの変換後のdecompile後は以下のようになります。
以下のようにsuperのコンストラクタが呼ばれたあと、つまりinjectされた後にgetValue()などが行われるため、問題なさそうです
抜粋

```kotlin
      super(context, attrs, defStyleAttr);
      Dep var10001 = this.dep;
      if (var10001 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      this.value = var10001.getValue();
```

```java
public final class CustomView extends Hilt_CustomView {
   @Inject
   public Dep dep;
   @NotNull
   private final String value;

   @NotNull
   public final Dep getDep() {
      Dep var10000 = this.dep;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      return var10000;
   }

   public final void setDep(@NotNull Dep var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.dep = var1;
   }

   @NotNull
   public final String getValue() {
      return this.value;
   }

   @JvmOverloads
   public CustomView(@NotNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
      Intrinsics.checkNotNullParameter(context, "context");
      super(context, attrs, defStyleAttr);
      Dep var10001 = this.dep;
      if (var10001 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      this.value = var10001.getValue();
   }

   // $FF: synthetic method
   public CustomView(Context var1, AttributeSet var2, int var3, int var4, DefaultConstructorMarker var5) {
      if ((var4 & 2) != 0) {
         var2 = (AttributeSet)null;
      }

      if ((var4 & 4) != 0) {
         var3 = 0;
      }

      this(var1, var2, var3);
   }

   @JvmOverloads
   public CustomView(@NotNull Context context, @Nullable AttributeSet attrs) {
      this(context, attrs, 0, 4, (DefaultConstructorMarker)null);
   }

   @JvmOverloads
   public CustomView(@NotNull Context context) {
      this(context, (AttributeSet)null, 0, 6, (DefaultConstructorMarker)null);
   }
```

## 色々いじってみる

### 複数パターン
以下のような場合も一応見てみましょう

```kotlin
@AndroidEntryPoint
class CustomView @JvmOverloads constructor(
  context: Context,
  attrs: AttributeSet? = null,
  defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
  @Inject lateinit var dep: Dep
  val value = dep.value
  @Inject lateinit var dep2: Dep
  val value2 = dep2.value
}
```

問題なさそうでした。

```java
public final class CustomView extends Hilt_CustomView {
   @Inject
   public Dep dep;
   @NotNull
   private final String value;
   @Inject
   public Dep dep2;
   @NotNull
   private final String value2;

   @NotNull
   public final Dep getDep() {
      Dep var10000 = this.dep;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      return var10000;
   }

   public final void setDep(@NotNull Dep var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.dep = var1;
   }

   @NotNull
   public final String getValue() {
      return this.value;
   }

   @NotNull
   public final Dep getDep2() {
      Dep var10000 = this.dep2;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep2");
      }

      return var10000;
   }

   public final void setDep2(@NotNull Dep var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.dep2 = var1;
   }

   @NotNull
   public final String getValue2() {
      return this.value2;
   }

   @JvmOverloads
   public CustomView(@NotNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
      Intrinsics.checkNotNullParameter(context, "context");
      super(context, attrs, defStyleAttr);
      Dep var10001 = this.dep;
      if (var10001 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      this.value = var10001.getValue();
      var10001 = this.dep2;
      if (var10001 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep2");
      }

      this.value2 = var10001.getValue();
   }
```

### コンストラクタを後ろに書くパターン

```kotlin
@AndroidEntryPoint
class CustomView : FrameLayout {
  @Inject lateinit var dep: Dep
  val value = dep.value

  @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
  ) : super(context, attrs, defStyleAttr)
}
```

問題なさそう

```java
public final class CustomView extends Hilt_CustomView {
   @Inject
   public Dep dep;
   @NotNull
   private final String value;

   @NotNull
   public final Dep getDep() {
      Dep var10000 = this.dep;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      return var10000;
   }

   public final void setDep(@NotNull Dep var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.dep = var1;
   }

   @NotNull
   public final String getValue() {
      return this.value;
   }

   @JvmOverloads
   public CustomView(@NotNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
      Intrinsics.checkNotNullParameter(context, "context");
      super(context, attrs, defStyleAttr);
      Dep var10001 = this.dep;
      if (var10001 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("dep");
      }

      this.value = var10001.getValue();
   }
```

### superに渡すパターン

IDE上、コンパイラでエラーになるので問題なさそうでした。

```kotlin
@AndroidEntryPoint
class CustomView : FrameLayout {
  @Inject lateinit var dep: Dep
  val value = dep.value

  @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
  ) : super(context, attrs, defStyleAttr + value.hashCode())
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27388/9e83394a-dea3-53e6-42c8-7dfb69000c2a.png)