I found some threads that explain why a Fragment
class should be static
(not non-static inner) like this. But can't understand the reason for this error message:
This fragment class should be public (...)
I use Android Studio 3.1.2 and this is a part of my codes:
public class MainActivity extends android.support.v7.app.AppCompatActivity {
// ...
}
class DefaultFragment extends android.support.v4.app.Fragment {
// ...
}
The fragment is supposed to be used only in MainActivity
.
EDIT: There is some other information in IDE message. But are about constructors:
From the Fragment documentation:
Every fragment must have an empty constructor, so it can be instantiated when restoring its activity's state. It is strongly recommended that subclasses do not have other constructors with parameters, since these constructors will not be called when the fragment is re-instantiated; instead, arguments can be supplied by the caller with setArguments(Bundle) and later retrieved by the Fragment with getArguments().
On orientation change, Activity recreated and framework creates new instance on fragment (and restores previous state).
So here to create instance of Fragment, framework asks to provide public constructer.
From Documentation of Fragment.Fragment()
Default constructor :
Every fragment must have an empty constructor
, so it can be instantiated when restoring its activity's state. It is strongly recommended that subclasses do not have other constructors with parameters, since these constructors will not be called when the fragment is re-instantiated; instead, arguments can be supplied by the caller with setArguments(Bundle)
and later retrieved by the Fragment
with getArguments()
.
Below is code form Activity.java class and you can analysis further in looking more codes of FragmentManager.dispatchMoveToState()
@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
........
if (savedInstanceState != null) {
mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
View.LAST_APP_AUTOFILL_ID);
if (mAutoFillResetNeeded) {
getAutofillManager().onCreate(savedInstanceState);
}
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
.....
}
It is also because inner classes hold a reference to their parent classes and this might leak the Activity.
Non static inner classes do hold a reference to their parent classes. The problem with making a Fragment inner class non-static is that you always hold a reference to the Activity. The GarbageCollector cannot collect your Activity. So you can 'leak' the Activity if for example the orientation changes. Because the Fragment might still live and gets inserted in a new Activity.
Check the detailed answer and the attempt to make the fragment