I am not able to understand one important aspect of Android software design which I am just starting out with, from what I know Fragment
design has been adopted in order to decouple the code, where the intuition is that the Activity
remains as is and Fragment
can be reused else where, maybe even in a different activity, or maybe along side other fragments, in something like a Master/Detail flow or landscape UI.
Okay so I have seen quite a handful of questions on SO asking as to why Fragments
are placed as static inner classes within an Activity
and the answer there is that if we do not make them static, the Fragment
may hold a reference to the activity and something like a screen rotation or a re-draw might leak the activity or something.
This brings me back to square one and I have the question that, well, if the Fragment design has been adopted in order to decouple the code, then why are we marrying the Fragment
to the Activity
by putting it inside the activity class and not putting them as standalone public classes? Isn't that totally contradicting to the very existence of Fragments?
What is the down side of having a project structure as such? Where each Fragment
is a separate class of its own? Given that my Fragment code can grow to like a 1000 lines especially when trying to do animations I am seeing this as far more neater, decoupled and reusable within activities other than it's intended parent Activity.
- Do we still suffer from the memory leak issue mentioned above?
- Am I missing something about the design logic? Please educate me.
- Is there a way where the Fragments stay as an inner class and still be used elsewhere? I might be missing something here as well... so do inform me.
Any other project design methods, concepts, corrections to my intuition are more than welcome since I am just starting out here, I would love to know all my options.
Thank you :)
This brings me back to square one and I have the question that, well, if the Fragment design has been adopted in order to decouple the code, then why are we marrying the Fragment to the Activity by putting it inside the activity class and not putting them as standalone public classes? Isn't that totally contradicting to the very existence of Fragments?
The main driver for fragments isn't decoupling but rather composition: reusable pieces of user interface that can be easily composed together in different configurations. From composability follows modularity and from it decoupling so yes, decoupling is there but it's not the primary concern.
Read on about fragment design philosophy.
The modularity coin has another side: if two things belong together such as an activity and a fragment that is only used with that activity, they are best kept together and not spread out all over the codebase so they are easier to evolve together. A project structure like in your question where activities and fragments are in separate packages would not really follow this principle.
One commonly seen way to keep fragments in separate classes but close to related activities and such is to use a naming prefix so they sort together in alphabetical lists within the same package: e.g. FooActivity with FooDetailsFragment.
For simple fragments where there isn't that much code and the fragment is only used in one activity, it's perfectly fine to have them as static inner classes in that activity.
Just try to be consistent so other people reading the code can easily find their way around in the codebase and the WTFs/minute code metric is kept low.
Do we still suffer from the memory leak issue mentioned above?
No, the leak applies only to non-static inner classes that hold a reference to the outer class. Package-level classes do not have any outer class to held a reference to.
Since fragments share the hosting activity's lifecycle, leaking the outer object is not really the concern with fragments. It's just that the framework needs to be able to instantiate the fragments without any outer class objects, and static
is a requirement for that.
Is there a way where the Fragments stay as an inner class and still be used elsewhere? I might be missing something here as well... so do inform me.
You can refer to public inner classes with the dot notation Outer.Inner
in code or Outer$Inner
with reflection (e.g. XML files).
While this is technically possible, doing so says you're relying on the internals of a class and that's a design smell. I'd really refer to inner classes in the outer class code itself.
I'd like to better know the logic against your idea; I make Fragments in their own class all the time, and my apps run like a rock during reorients. I do use an interface to speak to the managing Activity, use adapters to manage the Fragments, and perform basic accounting to ensure I'm not launching several background threads from re-loading.
So I check http://developer.android.com/guide/components/fragments.html
which is always worth a re-read, and whaddya know, the example at the bottom is just what you suggest, and I use every day: two public fragments in stand-alone classes that are attached to and by an activity.
If someone is really suggesting what you say, I suspect they are taking the line "A fragment must always be embedded in an activity and the fragment's lifecycle is directly affected by the host activity's lifecycle." way, way too literally; they mean embedded in the runtime.
gl hf!