{"record":{"id":"8d6875e3681e6a0b","repo":"yuliskov/SmartTube","slug":"videogridfragment-doesn-t-attached-to-the-activity","errorCode":null,"errorMessage":"VideoGridFragment doesn't attached to the activity","messagePattern":"VideoGridFragment doesn't attached to the activity","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/browse/video/VideoGridFragment.java","lineNumber":53,"sourceCode":"public class VideoGridFragment extends GridFragment implements VideoSection {\r\n    private static final String TAG = VideoGridFragment.class.getSimpleName();\r\n    private static final int RESTORE_MAX_SIZE = 10_000;\r\n    private VideoGroupObjectAdapter mGridAdapter;\r\n    private final List<VideoGroup> mPendingUpdates = new ArrayList<>();\r\n    private UriBackgroundManager mBackgroundManager;\r\n    private VideoGroupPresenter mMainPresenter;\r\n    private VideoCardPresenter mCardPresenter;\r\n    private int mSelectedItemIndex = -1;\r\n    private Video mSelectedItem;\r\n    private float mVideoGridScale;\r\n    private final Runnable mRestoreTask = this::restorePosition;\r\n\r\n    @Override\r\n    public void onCreate(@Nullable Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n\r\n        if (getActivity() == null) {\r\n            throw new IllegalStateException(\"VideoGridFragment doesn't attached to the activity\");\r\n        }\r\n\r\n        mMainPresenter = getMainPresenter();\r\n        mCardPresenter = isShorts() ? new ShortsCardPresenter() : new VideoCardPresenter();\r\n        mBackgroundManager = ((LeanbackActivity) getActivity()).getBackgroundManager();\r\n        mVideoGridScale = MainUIData.instance(getActivity()).getVideoGridScale();\r\n\r\n        setupAdapter();\r\n        setupEventListeners();\r\n        applyPendingUpdates();\r\n\r\n        if (getMainFragmentAdapter().getFragmentHost() != null) {\r\n            getMainFragmentAdapter().getFragmentHost().notifyDataReady(getMainFragmentAdapter());\r\n        }\r\n    }\r\n\r\n    protected VideoGroupPresenter getMainPresenter() {\r\n        return BrowsePresenter.instance(getContext());\r","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/yuliskov/SmartTube/blob/3de8d90593e0166f012ca18cc3c7ba45bfd68ac4/smarttubetv/src/main/java/com/liskovsoft/smartyoutubetv2/tv/ui/browse/video/VideoGridFragment.java#L35-L71","documentation":"VideoGridFragment.onCreate immediately requires a host activity because the very next lines cast getActivity() to LeanbackActivity to obtain the BackgroundManager and read UI prefs. If the fragment is created without an attached activity, getActivity() is null and it throws IllegalStateException instead of NPE-ing on the cast.","triggerScenarios":"Instantiating VideoGridFragment outside a FragmentManager transaction with a live host: manual new VideoGridFragment() followed by direct lifecycle calls, a detached/retained instance being re-created, or a fragment factory producing it before attachment.","commonSituations":"State restoration edge cases where the fragment is re-created during host teardown; tests instantiating the fragment directly with no host activity; code paths triggering grid creation from background callbacks after the activity is destroyed.","solutions":["Only create VideoGridFragment through a FragmentManager transaction (or leanback's PageRow/main-frame navigation) from a live LeanbackActivity host.","Never call lifecycle methods manually on the instance; let the FragmentManager drive them.","In tests, use FragmentScenario with a LeanbackActivity-compatible host so getActivity() is non-null at onCreate.","If triggering navigation from async callbacks, check that the host activity is alive (!isFinishing/isDestroyed) before switching sections."],"exampleFix":"// before — fragment driven manually with no host\nVideoGridFragment grid = new VideoGridFragment();\ngrid.onCreate(null); // getActivity() == null → IllegalStateException\n\n// after — attach through the framework; host is guaranteed at onCreate\ngetSupportFragmentManager().beginTransaction()\n        .replace(R.id.browse_frame, new VideoGridFragment())\n        .commit();","handlingStrategy":"validation","validationCode":"// only navigate while attached to a live host\nif (isAdded() && getActivity() instanceof LeanbackActivity && !getActivity().isFinishing()) {\n    getFragmentManager().beginTransaction()\n            .replace(R.id.browse_frame, new VideoGridFragment())\n            .commit();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never instantiate or drive fragment lifecycle methods manually.","Attach fragments via FragmentManager/leanback page-row navigation only.","Guard async navigation callbacks with isAdded() and !isFinishing()."],"tags":["android","android-tv","fragment","lifecycle","leanback"],"backgroundTag":"fragment-not-attached","analyzedSha":"3de8d90593e0166f012ca18cc3c7ba45bfd68ac4","analyzedAt":"2026-08-22T09:19:26.383Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}