質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

1639閲覧

Activityのオブジェクトを他のclass内で参照したい

lahaina

総合スコア8

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2019/07/25 04:18

前提・実現したいこと

androidで開発を行っている方に以下の点についてお聞きしたいと思います(android初心者かつ独学中です)。

・Activityのオブジェクトを他のclass内で参照したい場合、どのような対応を行うか。

例えば以下のようなケースを考えています。

Activity A(画面構成などの機能を持たせる)
Service B(位置情報管理の機能を持たせる)
class C(位置情報において特に情報取得の機能を持たせる)

この時、class C内でaddOnSuccessListenerメソッドを使おうとすると、引数にActivityのオブジェクトを渡す必要があります。自分が理解できた限りでは以下1.-4.のような対応を考えましたが、それぞれマイナス面があるように思います。

1.Activity A内にstaticフィールドを作成しActivity Aのオブジェクトを格納する。class C内で当該staticフィールドを参照する。ただし、Activity AがonDestroyされてもstaticフィールドは維持されるのでメモリリークが発生する可能性がある。メモリリーク回避のためにonDestroy時にstaticフィールドにnullを入れる。

2.Activity AにSerializableを実装させ、Intent、及びputExtraでActivity AのオブジェクトをService Bに渡す(以下のコード例。言語はJavaです。)。Class C内で当該オブジェクトを参照する。

java

1public class Activity extends AppCompatActivity implements Serializable { 2... 3 // Bind to the Service 4 intent = new Intent(this, Service.class); 5 intent.putExtra("Activity", Activity.this); 6 bindService(intent, mConnection, 7 Context.BIND_AUTO_CREATE);

ただし、Serializable は色々とリスクを含む(Effective Java 3rd 項目85)ので、できれば回避すべき。

3.Activity AにParcelableを実装させて、Intent、及びputExtraでService Bに渡す。ただし、Parcelableは実装に手間がかかる。

4.classに分け持たせたりせず、Activityに必要な機能はActivity内に書く。Activityのオブジェクトを他classに渡す心配する必要がなくなるが、Activityのコードが長くなる。初心者向けの本などではこう示されているものをよく見かける。ただし、後の拡張などを考えると、できれば機能ごとにclassに分けて書いておきたい。

自分が理解できた範囲だとこの程度ですが、皆様が普段どう対応されているかアドバイスいただけると大変助かります。Activityのオブジェクトを他classで参照したいケースは比較的ありそうですが、探し方が悪いのか検索しても見つけられず悩んでいます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kakajika

2019/07/25 05:34

Activityのインスタンスが必要なのは具体的にどのクラスのどのメソッドですか?位置情報を取得するだけなら、Serviceのインスタンスでも十分な気がします。UIが絡むとかでどうしてもActivityのインスタンスが必要なら、classCをService側に持たせるのではなくActivityから利用するべきです。
lahaina

2019/07/26 04:27

お返事ありがとうございます。Activityのインスタンスが必要なクラス、メソッドは以下のとおりです。 Taskクラス addOnSuccessListener (Activity activity, OnSuccessListener<? super TResult> listener) addOnFailureListener (Activity activity, OnFailureListener listener) 指定した位置情報取得に関する設定がクライアント側に反映されているかチェックしたく当該メソッドを記載しています。コードの該当部分は概ね以下のようになります。 settingsClient = LocationServices.getSettingsClient(コンテキストのインスタンス); settingsClient.checkLocationSettings(ロケーションセッティングリクエストのインスタンス) .addOnSuccessListener(アクティビティのインスタンス, new OnSuccessListener<LocationSettingsResponse>() { @Override public void onSuccess(.... また、「classCをService側に持たせるのではなくActivityから利用するべき」とのアドバイスありがとうございます。class C内でActivityを利用することばかり考えていました。ただ、今回Activityがバックグラウンドに移行した場合でも位置情報を取得し続けたいので、class CをActivityから利用するのは難しそうと思っていますが、いかがでしょうか。理解に誤りがありましたらご指摘下さい。
kakajika

2019/07/26 06:31

第一引数にActivityを取るaddOnSuccessListenerメソッドは、Activityのスコープで結果を受け取るためのものです。このリスナーはActivityがonStopの状態になると削除されてしまうので、Activityがバックグラウンドになったときには利用できません。 引数にActivityを取らない方のメソッドを使うべきかと思います。こちらならそもそもActivityを参照する理由もなくなるはずです。 https://developers.google.com/android/reference/com/google/android/gms/tasks/Task.html#addOnSuccessListener(com.google.android.gms.tasks.OnSuccessListener%3C?%20super%20TResult%3E)
lahaina

2019/07/26 08:34

お返事ありがとうございます。バックグラウンドで動かすのにActivityを渡すのは不自然だったのですね。大変助かりました。developersを読み直します。 なお、もしさらにご回答いただけるのであれば、普段Activityのインスタンスを他classであまり参照することはない(そうせざるを得ない場合は構成を見直した方が良い)のでしょうか。今回は私の不理解でしたが、staticフィールドやシリアライズを使ってまで参照せざるを得ないようなケースはどの程度あるのかな、と思ってしまいまして。
kakajika

2019/07/26 09:41

そのような実装が必要になるパターンは無いと言っていいと思います。Activityへの参照が必要になるような機能を持つクラスは、Activityから利用するべきです。詳しくは回答に書きますね。
guest

回答1

0

ベストアンサー

ご質問の1.〜3.の方法は、アンチパターンです。
そのような実装が必要になった時点で、そのクラスは本当にActivityのインスタンスへの参照が必要なクラスなのか、もしくはActivityから完全に切り離してしまっていいクラスなのかどうかを見直してみたほうが良いでしょう。
また、ActivityにSerializableやParcelableを実装して他のクラスに渡すということはできません。

Activityのインスタンスへの参照が必要なパターンは以下のようなものがありますが、

  • ActivityのUIに対する操作
  • Activityのライフサイクルに紐づく処理
  • Activity経由でOSが提供する機能へのアクセス

これらのケースでは基本的にご質問の4.のパターンで実装することになります。ただ、必ずしもすべてをActivity内に書く必要はなく、特定の機能に関する実装を別のクラスにまとめるのは良いアイデアだと思います。そのようなクラスの実装において、Activityのインスタンスへの参照が必要になる箇所では、メソッドの引数等にActivityを指定することで、これはActivityから呼ぶ必要があるメソッドだよと明示するようにします。addOnSuccessListenerのようにActivityを引数に取るメソッドがあるのは、そういう理由です。

投稿2019/07/26 10:31

kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lahaina

2019/07/26 10:59

お返事ありがとうございます。独学のためアンチパターンに陥っていることに気付き難く、本当に勉強になりました。ご説明もとてわかりやすかったです。 今回teratailを始めて利用したのですが、適切かつ丁寧にご提示いただき助かりました。また利用したいと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問