ジレンマ:フラグメントvsアクティビティを使用する場合:


786

Activitiesアプリケーションの単一の画面を表すFragmentsように設計されている一方で、ロジックが埋め込まれた再利用可能なUIレイアウトとして設計されていることは知っています。

ずっと前まで、開発すべきだと言っていたアプリケーションを開発しました。Activityアプリケーションの画面を表すを作成し、ViewPagerまたはのフラグメントを使用しましたGoogle MapsListFragment何度か再利用できるUIやその他のUIを作成することはめったにありません。

最近、私は唯一の2含むプロジェクトにつまずいActivities1がありSettingsActivity、他方ですMainActivity。のレイアウトには、MainActivity非表示のフルスクリーンUIフラグメントが多数含まれており、1つだけが表示されています。Activity論理多く存在するFragmentTransitionsアプリケーションの異なる画面間。

このアプローチについて私が気に入ったのは、アプリケーションがを使用しているため、ActionBarそのままの状態であり、画面切り替えアニメーションと一緒に移動しないことActivityです。これにより、画面の遷移がより滑らかになります。

だから私はこのトピックに関するあなたの現在の開発方法を共有することを求めていると思います、それは一見すると意見ベースの質問のように見えるかもしれませんが、私はそれをAndroidの設計とアーキテクチャの質問と見なします...実際には意見ベースのもの。

UPDATE(2014年1月5日):によってこのプレゼンテーションに続いて、エリック・バークから広場、(私が言っているのAndroid開発者のための便利なツールの多くの偉大なプレゼンテーションであると私は広場にどのような方法で関連しておりません)

http://www.infoq.com/presentations/Android-Design/

過去数か月の個人的な経験から、アプリケーションを構築する最善の方法は、アプリケーションのフローを表すフラグメントのグループを作成し、それらすべてのフラグメントを1つに表示することであることがわかりましたActivity。したがって、基本的にActivitiesは、アプリケーション内のフローの数と同じ数になります。そうすることで、アクションバーはすべてのフローの画面にそのまま残りますが、フローを変更すると再作成されるため、非常に理にかなっています。エリックバークが述べているように、そして私も実現しActivitiesたように、彼が「神」の活動と呼んでいるものを混乱させるので、できるだけ少ないものを使用するという哲学はすべての状況に当てはまるわけではありません。


2
SOで私の記事をチェックアウト- stackoverflow.com/questions/24647078/...
私の神

回答:


271

専門家はあなたを教えてくれます:「私はUIが表示されたら、私が使用するかどうかを知っているだろうActivityFragment」。最初はこれは意味がありませんが、やがて、必要Fragmentかどうかを実際に知ることができます。

私にとって非常に役立つとわかった良い習慣があります。私が娘に何かを説明しようとしていたとき、それは私に起こりました。

つまり、画面を表すボックスを想像してみてください。このボックスに別の画面をロードできますか?新しいボックスを使用する場合、最初のボックスから複数のアイテムをコピーする必要がありますか?答えが「はい」の場合はFragments、ルートを使用する必要があります。ルートActivityは複製されたすべての要素を保持できるため、要素を作成する時間を節約でき、ボックスの一部を交換するだけで済みます。

ただし、常にボックスコンテナー()が必要です。そうしないActivity、パーツが分散されます。内部に部品が入った1つのボックスです。

箱を誤用しないように注意してください。Android UXのエキスパートは、明示的に別のをロードする必要がある場合(YouTubeで見つけることができます)Activity、代わりにFragment(カテゴリのあるナビゲーションドロワーを扱う場合など)を使用することをお勧めします。に慣れたらFragments、すべてのビデオを見ることができます。さらに、それらは必須の資料です。

今すぐUIを見て、Activityまたはが必要かどうかを判断できますFragmentか?新しい見方をしましたか?あなたがしたと思います。


4
あなたが言及したYouTubeフィードへのリンクはありますか?「Android UXエキスパート」と「Android UX」を検索しましたが、どの動画について話しているのか完全にはわかりません。

2
1年以上前に視聴しました。UXについて話しているAndroid開発者の公式を検索
sandalone

1
考慮事項の1つの例:アクティビティにはparentActivityがあるため、通知から入るときにバックスタックを合成できますが、そのようなparentFragmentはないと思います。
fikr4n 2017


@ToolmakerSteveはい、それはgetParentFragmentですが、私が意図したものではありません
。developer.android.com/ guide / topics / manifest /…を

129

私の哲学はこれです:

絶対に必要な場合にのみ、アクティビティを作成します。一連のフラグメントトランザクションをコミットするために利用可能なバックスタックを使用して、アプリでできるだけ少ないアクティビティを作成しようとしています。また、さまざまなフラグメント間の通信は、アクティビティ間でデータをやり取りするよりもはるかに簡単です。

アクティビティの遷移は高価ですよね?少なくとも私はそう信じています-古いアクティビティを破棄/一時停止/停止し、スタックにプッシュしてから、新しいアクティビティを作成/開始/再開する必要があるためです。

フラグメントが導入されて以来、それは私の哲学にすぎません。


2
本当ですが、あなたが書いたように、時にはアクティビティを使用する必要があります。1つの例はカメラ画面です。横長モードで使用する方が良いでしょう。別の例は、カスタマイズされたappWidgetを(「デスクトップ」-ランチャーアプリに)配置したときに表示される構成画面です。
Android開発者

あなたが答えて、あなたの経験を共有してくれてありがとうそれで、アプリケーションのアーキテクチャがそれを許可するなら、アプリケーションを1つのアクティビティに制限し、すべての画面にフラグメントを使用することはAndroidの良い習慣だと思いますか?
Emil Adz 2013

1
それでは、お互いの「状態」を渡す必要があるフラグメントの問題をどのように解決しますか?すべてのフラグメントのすべての状態が1つのアクティビティに存在する必要があります。そうでなければ、シングルトンを使用する必要があります。
Mr_E 2016

36
さまざまなフラグメント間の通信は、アクティビティ間でデータをやり取りするよりもはるかに簡単だとは思いません。
デニー

3
少なくとも、onActivityResult()フラグメントのコールバックより安全で簡単です。
CoolMind 2018年

59

まあ、Googleの講義(多分、ここでは、覚えていません)によると、可能な限りフラグメントを使用することを検討してください。コードを維持および制御しやすくなるためです。

ただし、フラグメントをホストするアクティビティーがフラグメント間をナビゲート/通信する必要があるため、場合によっては複雑になる可能性があると思います。

何が一番いいか自分で決めるべきだと思います。通常、アクティビティをフラグメントに、またはその逆に変換することはそれほど難しくありません。

さらに読みたい場合は、このディレマに関する投稿をここに作成しました。


5
あなたが答えて、あなたの経験を共有してくれてありがとうそれで、アプリケーションのアーキテクチャがそれを許可するなら、アプリケーションを1つのアクティビティに制限し、すべての画面にフラグメントを使用することはAndroidの良い習慣だと思いますか?
Emil Adz 2013

プロジェクトによって異なりますが、複雑すぎる場合は、複数のアクティビティに分けることもできます。いずれかの方法を使用することを恐れないでください。両方を使用することもできます。たぶん、アクティビティの代わりにフラグメントを使用するのが難しい場合があります。フラグメントを使用する必要があると思いますが、邪魔になりすぎた場合は、どこにでも強制的に配置しないでください...
android developer

ActionBarのこの影響をそのままに保ち、すべてのコンテンツが切り替えられている場合はどうなりますか?アクティビティでこれを達成することは可能ですか?
Emil Adz 2013


27

すべてのケースでアクティビティよりもフラグメントを優先する理由。

  • 活動は高価です。Fragmentでは、ビューとプロパティの状態が分離backstackされます。フラグメントがにあるときはいつでも、そのビューは破棄されます。したがって、アクティビティよりもはるかに多くのフラグメントをスタックできます。

  • Backstack操作。を使用するとFragmentManager、すべてのフラグメントをクリアしたり、フラグメントなどより多くを挿入したりするのが簡単です。しかし、Activityの場合、それらを操作することは悪夢になります。

  • 予測可能なライフサイクル。ホストアクティビティがリサイクルされない限り。バックスタックのフラグメントはリサイクルされません。したがって、FragmentManager::getFragments()特定のフラグメントを見つけるために使用することが可能です(推奨されません)。


こんにちは、法よりもFragの利点についてのレビューを読みました。GithubRepoで同じことを示すプロジェクトはありますか?
Ümañgßürmån

24

Jetpack以降、シングルアクティビティアプリが推奨アーキテクチャです。特にナビゲーションアーキテクチャコンポーネントで役立ちます

ソース


これありがとう!
シモン・ガルシア

1
今日は初めてJetpackについて読みました。:)フラグメントが導入されて以来、シングルアクティビティアプリを構築しています。マルチアクティビティははるかに複雑です。
驚くべきJan

1
@TheincredibleJanそうです、Jetpackよりずっと前にシングルアクティビティアプリアーキテクチャの方が優れたソリューションでした
Francis

12

私の意見では、それは実際には関係ありません。考慮すべき重要な要素は

  1. UIの一部(メニューなど)を再利用する頻度
  2. アプリはタブレット用ですか?

フラグメントの主な用途は、マルチペインアクティビティを構築することです。これにより、タブレット/電話対応のアプリに最適です。


フラグメントの主な用途は、カスタムビューとは考えずにカスタムビューを作成することです。それがとにかく起こることです。もともとGoogleから表示されたフラグメントは、タブレットレスポンシブアプリを作成するための便利な方法であるため、必要に応じてさまざまなアクティビティに固定できます。ビューにコードを添付して、カスタムビューを作成せずに、必要な場所に固定できるようにする方法。
Lassi Kinnunen、

11

アクティビティは、Intentを通じて共有および開始できるアプリケーションのブロック/コンポーネントであることを忘れないでください!したがって、アプリケーションの各アクティビティは、1種類のタスクのみを解決する必要があります。アプリケーションにタスクが1つしかない場合は、1つのアクティビティと、必要に応じて多くのフラグメントが必要だと思います。もちろん、別のタスクを解決する将来のアクティビティでフラグメントを再利用できます。このアプローチにより、タスクが明確かつ論理的に分離されます。また、フラグメントのセットごとに異なるインテントフィルターパラメーターで1つのアクティビティを維持する必要はありません。要件に基づいて、開発プロセスの設計段階でタスクを定義します。


私たちのアプリケーションでは、アクティビティの1つの種類のタスクは、ナビゲーションドロワーを保持してさまざまなフラグメントを入力することです。:)なぜフラグメントの意図に取り組む必要があるのですか?グローバルデータの「グローバル」データクラスへの静的参照を保持し、いくつかの値をフラグメントのインスタンス作成メソッドに渡すことは明確で論理的です。
信じられないほどのJan

9

これにはあなたが認識している以上のことがあり、起動されたアクティビティが呼び出し元のアクティビティを暗黙的に破棄しないことを覚えておく必要があります。もちろん、ユーザーがボタンをクリックしてページに移動し、そのページのアクティビティを開始して現在のアクティビティを破棄するように設定できます。これは多くのオーバーヘッドを引き起こします。私があなたに与えることができる最高のガイドは:

**メインアクティビティとこのアクティビティを同時に開くことが理にかなっている場合にのみ、新しいアクティビティを開始します(複数のウィンドウを考えてみてください)。

複数のアクティビティを持つことが理にかなっている良い例は、Googleドライブです。メインアクティビティはファイルエクスプローラを提供します。ファイルを開くと、そのファイルを表示するための新しいアクティビティが起動します。最近開いたアプリのボタンを押すと、開いているドキュメントを閉じずにブラウザーに戻り、最初のドキュメントと並行して別のドキュメントを開くこともできます。


「(複数のウィンドウを考える)ことが主な活動と同時に開いて、このいずれかを持っていることは理にかなっている場合にのみ、新たな活動を開始します。」私はそうは思いません。その状況はフラグメント attach / detachメソッドを使用してうまく解決されます。
ToolmakerSteve 2016

7

私がしたこと:可能な場合はフラグメントを少なくする。残念ながら、ほとんどの場合それは可能です。だから、私は多くの断片と少しの活動に終わります。私が認識したいくつかの欠点:

  • ActionBar&メニュー:2つのフラグメントのタイトル、メニューが異なると、
    処理が難しくなります。例:新しいフラグメントを追加するときに、アクションバーのタイトルを変更できますが、ポップbackstackすると、古いタイトルを復元する方法がありません。この場合、すべてのフラグメントでツールバーが必要になる場合がありますが、もっと時間を費やすでしょう。
  • 必要なときstartForResult、アクティビティは持っていますが、フラグメントは持っていません。
  • デフォルトでは遷移アニメーションはありません

これに対する私の解決策は、アクティビティを使用してフラグメントを内部にラップすることです。したがって、アクションバー、メニューstartActivityForResult、アニメーションなどが分かれています...


1
非常に役立つポイント、ありがとうございます。「フラグメントをラップするアクティビティ」を明確にできますか?フラグメントごとに個別のアクティビティを作成しましたか?もしそうなら、フラグメントはまったく必要ですか?
ToolmakerSteve

3
タイトルなどを復元する方法があります。getSupportFragmentManager().addOnBackStackChangedListenerリスナーを追加するために使用します。そのリスナーで現在のフラグメントを取得してから、タイトルなどを設定します。
バベイ

4

fragmentオーバーアクティビティの大きな利点の1つは、フラグメントに使用されるコードをさまざまなアクティビティに使用できるため、アプリケーション開発でコードを利用できることです。


3
どうやって?例を挙げていただけませんか?
sofs1

1
@ sofs1あなたの質問はあまり意味がありません。フラグメント内のコードは、フラグメントがどのアクティビティから起動されたかに関係なく同じままです。
信じられないほどのJan

@TheincredibleJanしかし、「2番目のアクティビティがどのアクティビティからインスタンス化されても、アクティビティ内のすべてのコードは同じままである」とも言えませんか?違いはわかりません。
iforce2d

3

ためのベースを提供するために使用するアプリケーションごとに活動をfragment 使用fragment画面で、 fragmentsあるライト重量と比較して、activites フラグメントはれる再使用可能な 断片がさ適し電話&タブレットの両方をサポートするアプリの


2

それらの1つを自由に使用できます。
基本的に、どちらがアプリに最適かを評価する必要があります。業務フローを管理する方法と、データ設定を保存/管理する方法について考えます。

Fragmentsがどのようにガーベッジ・データを保管するかを考えてみてください。フラグメントを実装すると、フラグメントで埋めるアクティビティルートができます。したがって、フラグメントが多すぎる多くのアクティビティを実装しようとする場合は、アプリのパフォーマンスを考慮する必要があります。つまり、2つのコンテキストライフサイクルを操作している(大まかに言えば)、複雑さを覚えておく必要があります。

覚えておいてください:フラグメントを使用する必要がありますか?なぜ私はいけないのですか?

よろしく。


1

ユーザーエクスペリエンスを向上させるためにフラグメントを使用しています。たとえば、ボタンがあり、それを実行したい場合は、ボタンをクリックしたときにWebサービスがあるとしましょう。親アクティビティにフラグメントをアタッチします。

if (id == R.id.forecast) {

    ForecastFragment forecastFragment = new ForecastFragment();
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.main_content, forecastFragment);
    ft.addToBackStack("backstack");
    forecastFragment.setArguments(b);
    ft.commit();
}

このようにして、ユーザーは別のアクティビティに移動する必要がなくなります。

2つ目は、回転中にフラグメントを簡単に処理できるため、フラグメントを好みます。


その例がユーザーエクスペリエンスを向上させる理由は何ですか?アクティビティやフラグメントを実行していることを、どのようにして知る(または気にする)のでしょうか。
iforce2d

1

実際に何を構築したいかによります。たとえば、navigation drawerフラグメントを使用します。タブも使用fragmentsします。別の良い実装は、あなたが持っている場所ですlistview。電話を回転させて行をクリックすると、画面の残りの半分にアクティビティが表示されます。個人的に、私が使用fragmentsし、fragment dialogsそれがより専門的であるとして、。加えて、それらはローテーションで簡単に処理されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.