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.
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 :)
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
Java static nested class A static class is a class that is created inside a class, is called a static nested class in Java. It cannot access non-static data members and methods. It can be accessed by outer class name. It can access static data members of the outer class, including private.
A non-static nested class has full access to the members of the class within which it is nested. A static nested class does not have a reference to a nesting instance, so a static nested class cannot invoke non-static methods or access non-static fields of an instance of the class within which it is nested.
A static inner class is a nested class which is a static member of the outer class. It can be accessed without instantiating the outer class, using other static members. Just like static members, a static nested class does not have access to the instance variables and methods of the outer class.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With