KINTO Tech Blog
Development

【Android】ApplicationクラスでAPIコールは避けたい

Cover Image for 【Android】ApplicationクラスでAPIコールは避けたい

この記事は KINTOテクノロジーズアドベントカレンダー2024 の2日目の記事です🎅🎄

はじめに

こんにちは!KTCでAndroidエンジニアをしている長谷川です!

本記事ではAndroid開発において、Applicationクラスでやりがちなミスとその対処法の一例を紹介します。

Applicationクラスとは

AndroidにおけるApplicationクラスとは公式ドキュメントを参考に、以下の説明ができそうです。

「Base class for maintaining global application state. It is instantiated before any other class for your application/package is created.」

つまりグローバルで状態を管理できること、他のどのクラスよりも先にインスタンス化されるということです。

プロジェクトによって色々な実装をしているケースがあると思いますが、一般的には以下のようにアプリ内で使用するライブラリの初期化をしたり、DIの設定を行うことが多いと思います。

class MyApplication: Application() {
  override fun onCreate() {
    super.onCreate()
    // ライブラリ初期化
    // DIの設定
  }
}

もしここでアプリケーション起動時にサーバーからデータが欲しくて、API通信をした場合どうなるでしょうか?

class MyApplication: Application() {
  override fun onCreate() {
    super.onCreate()
    // ライブラリ初期化
    // DIの設定
    // APIコール
  }
}

少なくとも私はこのようなコードを何回か見たことがあります。
このコードはすぐには問題にならないですが、将来的に問題を引き起こす可能性があります。
本記事ではどのような場合に、このコードが問題になりうるか、説明します。

4つのアプリコンポーネントとApplicationクラスの関係

ApplicationクラスでAPIコールを行うと何が問題になるかを説明するためには、Androidの4つのアプリコンポーネントについての理解が必要です。
下記の画像は4つのアプリコンポーネントと、それぞれのコンポーネントでよく使用される機能を表しています。

Activityは主にアプリの画面の責務を持ち、最も使用されると思います。
また通知の機能を持つアプリはServiceを使用することが多いと思います。加えてWidgetの機能を持つアプリではBroadcast Receiverを利用することになると思います。Content Providerを使ったことがある方は少ないかもしれないですが、自アプリのデータを他アプリに公開したい場合などに使用できます。

android-4-component.jpg

注意して欲しいことは、これらのコンポーネントのどれかが動いている場合、Applicationクラスがインスタンス化されているということです。特にActivity以外のコンポーネントはユーザーが明示的にアプリを開いていないことがあります。

例えば、Widgetを持つアプリの場合、端末の再起動などでウィジェットが作成されますが、この時にApplicationクラスはインスタンス化される可能性があります。
もしApplicationクラスにAPIコールが記述されている場合、このタイミングでユーザーはアプリを開いていなくても(そしてほとんどの場合、開発者も意図しないタイミングで)APIコールが行われてしまいます。

通知の機能を持つアプリの場合、push通知が届くタイミングでApplicationクラスがインスタンス化される可能性があります。
もし複数のユーザーにまとめてpush通知を送信した場合、ほぼ同タイミングでAPIコールを行ってしまい、ある意味DDoS攻撃のような状態になるリスクがあります。
特にこの問題はユーザー数の増加など後になって発覚することもあり、知識として知っておくことが大切です。

最初にAPIコールしたい場合どうする?

対処方法はたくさんあると思うので、正解はありませんが一例を紹介します。
データは必要な時に必要な分だけ取得するべきなので、4つのコンポーネント内でそれぞれ取得しましょう。
その際に取得したデータを4つのコンポーネント内で使いまわしたい場合は、永続化をしたり、データをApplicationに保持させたり、DIでライフサイクルスコープをSingletonに設定したクラスに保持させておくことが可能です。

おわりに

お疲れ様でした。短い記事ですが、今回はApplicationクラスのライフサイクルと気をつけたい実装について解説しました。
本記事ではApplicationクラスに記述されたAPIコールを例に説明しましたが、例えばアプリ起動のイベントなどをApplicationクラスで送信することもよくある間違いの1つかなと思います。
上記で説明した通り、Applicationクラスのインスタンス化は必ずしもユーザーが明示的にアプリを起動したタイミングとは一致しないためです。
ユーザーがアプリを起動したイベントであれば、Activityに記述するべきです。もしマルチアクティビティを採用しているアプリだとしても、アプリの入り口の導線を正しく把握しましょう。

本記事がどなたかの助けになれば幸いです。

※Android ロボットは、Google が作成および提供している作品から複製または変更したものであり、クリエイティブ・コモンズ表示 3.0 ライセンスに記載された条件に従って使用しています。

Facebook

関連記事 | Related Posts

We are hiring!

【プロジェクトマネージャー】モバイルアプリ開発G/大阪

モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。

【iOSエンジニア】モバイルアプリ開発G/大阪

モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。