Skip to content

Commit a6ca6be

Browse files
committed
Fix activity recreation crashes with tabs and complex view hierarchies
When "Don't keep activities" is enabled (or the system destroys the activity to reclaim memory), NativeScript apps using ViewPager2-based tabs (e.g. @nativescript-community/ui-material-tabs) crash on foregrounding. Two root causes are addressed: 1. ActionBar's disposeNativeView() nulled _actionItems, causing "Cannot read properties of null (reading 'addItem')" when the action bar was recreated during _setupUI after activity destruction. 2. Android's FragmentManager restores all fragments from savedInstanceState during super.onCreate(), including third-party fragments (ViewPager2's f0, f1, etc.). NativeScript's _tearDownUI/_setupUI cycle rebuilds the entire view tree from scratch, leaving these restored fragments orphaned — they reference container views that no longer exist, causing "Fragment does not have a view" errors. We now remove non-NativeScript fragments immediately after super.onCreate() while preserving core's own fragments (tagged fragment{id}[{depth}]) which have a proper restoration path via _processNextNavigationEntry and FragmentCallbacksImplementation.onCreateView.
1 parent 69dc869 commit a6ca6be

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

packages/core/ui/action-bar/action-bar-common.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export class ActionBarBase extends View implements ActionBarDefinition {
2929
public effectiveContentInsetRight: number;
3030

3131
disposeNativeView() {
32-
this._actionItems = null;
3332
super.disposeNativeView();
3433
}
3534

packages/core/ui/frame/index.android.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,33 @@ export class ActivityCallbacksImplementation implements AndroidActivityCallbacks
861861
const isRestart = !!savedInstanceState && moduleLoaded;
862862
superFunc.call(activity, isRestart ? savedInstanceState : null);
863863

864+
if (isRestart && activity.getSupportFragmentManager) {
865+
// Remove restored fragments that NativeScript will recreate via _setupUI/createNativeView.
866+
// NativeScript tears down and rebuilds the entire view tree on activity recreation,
867+
// so restored fragments (especially from ViewPager2/tabs) become orphaned without views.
868+
// NativeScript core's own fragments use tags like "fragment{id}[{depth}]" and are
869+
// handled by _processNextNavigationEntry. We remove all non-NativeScript fragments.
870+
const fm = activity.getSupportFragmentManager();
871+
const fragments = fm.getFragments();
872+
if (fragments && fragments.size() > 0) {
873+
const ft = fm.beginTransaction();
874+
let removed = false;
875+
for (let i = fragments.size() - 1; i >= 0; i--) {
876+
const f = fragments.get(i);
877+
if (!f) continue;
878+
const tag = f.getTag();
879+
if (tag && tag.startsWith('fragment')) {
880+
continue;
881+
}
882+
ft.remove(f);
883+
removed = true;
884+
}
885+
if (removed) {
886+
ft.commitNowAllowingStateLoss();
887+
}
888+
}
889+
}
890+
864891
// Try to get the rootViewId form the saved state in case the activity
865892
// was destroyed and we are now recreating it.
866893
if (savedInstanceState) {

0 commit comments

Comments
 (0)