fix: android cleanup after new fragment handling

This commit is contained in:
Martin Guillon
2020-10-27 21:00:10 +01:00
parent 893431a66d
commit e6fc8784e1
3 changed files with 27 additions and 143 deletions

View File

@ -91,57 +91,6 @@ function initializeNativeClasses() {
return tabItem.nativeViewProtected;
}
public onDestroyView() {
const hasRemovingParent = this.getRemovingParentFragment();
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap);
this.owner._originalBackground = this.owner.backgroundColor || new Color('White');
this.owner.nativeViewProtected.setBackgroundDrawable(bitmapDrawable);
this.backgroundBitmap = null;
let thisView = this.getView();
if (thisView) {
let thisViewParent = thisView.getParent();
if (thisViewParent && thisViewParent instanceof android.view.ViewGroup) {
thisViewParent.removeView(thisView);
}
}
}
super.onDestroyView();
}
public onPause(): void {
const hasRemovingParent = this.getRemovingParentFragment();
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected);
}
super.onPause();
}
private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap {
// Another way to get view bitmap. Test performance vs setDrawingCacheEnabled
// const width = view.getWidth();
// const height = view.getHeight();
// const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
// const canvas = new android.graphics.Canvas(bitmap);
// view.layout(0, 0, width, height);
// view.draw(canvas);
view.setDrawingCacheEnabled(true);
const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bitmap;
}
}
@NativeClass
@ -250,7 +199,7 @@ function iterateIndexRange(index: number, eps: number, lastIndex: number, callba
@CSSType('BottomNavigation')
export class BottomNavigation extends TabNavigationBase {
private _contentView: org.nativescript.widgets.ContentLayout;
private _contentViewId: number = -1;
private _contentViewId = -1;
private _bottomNavigationBar: org.nativescript.widgets.BottomNavigationBar;
private _currentFragment: androidx.fragment.app.Fragment;
private _currentTransaction: androidx.fragment.app.FragmentTransaction;
@ -347,8 +296,8 @@ export class BottomNavigation extends TabNavigationBase {
const lastIndex = this.items.length - 1;
const offsideItems = 0;
let toUnload = [];
let toLoad = [];
const toUnload = [];
const toLoad = [];
iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i));
@ -610,7 +559,7 @@ export class BottomNavigation extends TabNavigationBase {
tabItemSpec.backgroundColor = backgroundColor ? backgroundColor.android : this.getTabBarBackgroundArgbColor();
// COLOR
let itemColor = this.selectedIndex === tabStripItem._index ? this._selectedItemColor : this._unSelectedItemColor;
const itemColor = this.selectedIndex === tabStripItem._index ? this._selectedItemColor : this._unSelectedItemColor;
const color = itemColor || titleLabel.style.color;
tabItemSpec.color = color && color.android;
@ -669,7 +618,7 @@ export class BottomNavigation extends TabNavigationBase {
image = this.getFixedSizeIcon(image);
}
let imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
const imageDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), image);
return {
drawable: imageDrawable,
@ -681,7 +630,7 @@ export class BottomNavigation extends TabNavigationBase {
}
private getIconInfo(tabStripItem: TabStripItem, color?: Color): IconInfo {
let originalIcon = this.getOriginalIcon(tabStripItem, color);
const originalIcon = this.getOriginalIcon(tabStripItem, color);
return this.getDrawableInfo(originalIcon);
}
@ -841,7 +790,7 @@ export class BottomNavigation extends TabNavigationBase {
}
public setTabBarTextTransform(value: TextTransform): void {
let items = this.tabStrip && this.tabStrip.items;
const items = this.tabStrip && this.tabStrip.items;
if (items) {
items.forEach((tabStripItem) => {
if (tabStripItem.label && tabStripItem.nativeViewProtected) {

View File

@ -81,7 +81,7 @@ function getAttachListener(): android.view.View.OnAttachStateChangeListener {
export class Frame extends FrameBase {
public _originalBackground: any;
private _android: AndroidFrame;
private _containerViewId: number = -1;
private _containerViewId = -1;
private _tearDownPending = false;
private _attachedToWindow = false;
private _cachedTransitionState: TransitionState;
@ -190,7 +190,7 @@ export class Frame extends FrameBase {
// simulated navigation (NoTransition, zero duration animator) and thus the fragment immediately disappears;
// the user only sees the animation of the entering fragment as per its specific enter animation settings.
// NOTE: we are restoring the animation settings in Frame.setCurrent(...) as navigation completes asynchronously
let cachedTransitionState = getTransitionState(this._currentEntry);
const cachedTransitionState = getTransitionState(this._currentEntry);
if (cachedTransitionState) {
this._cachedTransitionState = cachedTransitionState;
@ -425,7 +425,7 @@ export class Frame extends FrameBase {
navigationTransition = null;
}
let isNestedDefaultTransition = !currentEntry;
const isNestedDefaultTransition = !currentEntry;
_setAndroidFragmentTransitions(animated, navigationTransition, currentEntry, newEntry, this._android.frameId, transaction, isNestedDefaultTransition);
@ -659,7 +659,7 @@ function clearEntry(entry: BackstackEntry): void {
}
let framesCounter = 0;
let framesCache = new Array<WeakRef<AndroidFrame>>();
const framesCache = new Array<WeakRef<AndroidFrame>>();
class AndroidFrame extends Observable implements AndroidFrameDefinition {
public rootViewGroup: android.view.ViewGroup;
@ -689,7 +689,7 @@ class AndroidFrame extends Observable implements AndroidFrameDefinition {
}
public get activity(): androidx.appcompat.app.AppCompatActivity {
let activity: androidx.appcompat.app.AppCompatActivity = this.owner._context;
const activity: androidx.appcompat.app.AppCompatActivity = this.owner._context;
if (activity) {
return activity;
}
@ -708,12 +708,12 @@ class AndroidFrame extends Observable implements AndroidFrameDefinition {
}
public get actionBar(): android.app.ActionBar {
let activity = this.currentActivity;
const activity = this.currentActivity;
if (!activity) {
return undefined;
}
let bar = activity.getActionBar();
const bar = activity.getActionBar();
if (!bar) {
return undefined;
}
@ -727,7 +727,7 @@ class AndroidFrame extends Observable implements AndroidFrameDefinition {
return activity;
}
let frames = _stack();
const frames = _stack();
for (let length = frames.length, i = length - 1; i >= 0; i--) {
activity = frames[i].android.activity;
if (activity) {
@ -812,7 +812,7 @@ function startActivity(activity: androidx.appcompat.app.AppCompatActivity, frame
function getFrameByNumberId(frameId: number): Frame {
// Find the frame for this activity.
for (let i = 0; i < framesCache.length; i++) {
let aliveFrame = framesCache[i].get();
const aliveFrame = framesCache[i].get();
if (aliveFrame && aliveFrame.frameId === frameId) {
return aliveFrame.owner;
}
@ -975,22 +975,10 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
@profile
public onDestroyView(fragment: org.nativescript.widgets.FragmentBase, superFunc: Function): void {
try {
if (Trace.isEnabled()) {
Trace.write(`${fragment}.onDestroyView()`, Trace.categories.NativeLifecycle);
}
const hasRemovingParent = fragment.getRemovingParentFragment();
if (hasRemovingParent) {
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), this.backgroundBitmap);
this.frame._originalBackground = this.frame.backgroundColor || new Color('White');
this.frame.nativeViewProtected.setBackgroundDrawable(bitmapDrawable);
this.backgroundBitmap = null;
}
} finally {
superFunc.call(fragment);
if (Trace.isEnabled()) {
Trace.write(`${fragment}.onDestroyView()`, Trace.categories.NativeLifecycle);
}
superFunc.call(fragment);
}
@profile
@ -1024,17 +1012,7 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks {
@profile
public onPause(fragment: org.nativescript.widgets.FragmentBase, superFunc: Function): void {
try {
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
const hasRemovingParent = fragment.getRemovingParentFragment();
if (hasRemovingParent) {
this.backgroundBitmap = this.loadBitmapFromView(this.frame.nativeViewProtected);
}
} finally {
superFunc.call(fragment);
}
superFunc.call(fragment);
}
@profile
@ -1101,7 +1079,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
// If there is savedInstanceState and moduleLoaded is false we are restarted but process was killed.
// For now we treat it like first run (e.g. we are not passing savedInstanceState so no fragments are being restored).
// When we add support for application save/load state - revise this logic.
let isRestart = !!savedInstanceState && moduleLoaded;
const isRestart = !!savedInstanceState && moduleLoaded;
superFunc.call(activity, isRestart ? savedInstanceState : null);
// Try to get the rootViewId form the saved state in case the activity
@ -1265,7 +1243,7 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
}
@profile
public onRequestPermissionsResult(activity: any, requestCode: number, permissions: Array<String>, grantResults: Array<number>, superFunc: Function): void {
public onRequestPermissionsResult(activity: any, requestCode: number, permissions: Array<string>, grantResults: Array<number>, superFunc: Function): void {
if (Trace.isEnabled()) {
Trace.write('NativeScriptActivity.onRequestPermissionsResult;', Trace.categories.NativeLifecycle);
}

View File

@ -82,49 +82,6 @@ function initializeNativeClasses() {
return tabItem.view.nativeViewProtected;
}
public onDestroyView() {
const hasRemovingParent = this.getRemovingParentFragment();
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap);
this.owner._originalBackground = this.owner.backgroundColor || new Color('White');
this.owner.nativeViewProtected.setBackground(bitmapDrawable);
this.backgroundBitmap = null;
}
super.onDestroyView();
}
public onPause(): void {
const hasRemovingParent = this.getRemovingParentFragment();
// Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments.
// TODO: Consider removing it when update to androidx.fragment:1.2.0
if (hasRemovingParent && this.owner.selectedIndex === this.index) {
this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected);
}
super.onPause();
}
private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap {
// Another way to get view bitmap. Test performance vs setDrawingCacheEnabled
// const width = view.getWidth();
// const height = view.getHeight();
// const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
// const canvas = new android.graphics.Canvas(bitmap);
// view.layout(0, 0, width, height);
// view.draw(canvas);
view.setDrawingCacheEnabled(true);
const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bitmap;
}
}
const POSITION_UNCHANGED = -1;
@ -442,7 +399,7 @@ export class TabView extends TabViewBase {
private _tabLayout: org.nativescript.widgets.TabLayout;
private _viewPager: androidx.viewpager.widget.ViewPager;
private _pagerAdapter: androidx.viewpager.widget.PagerAdapter;
private _androidViewId: number = -1;
private _androidViewId = -1;
public _originalBackground: any;
constructor() {
@ -549,8 +506,8 @@ export class TabView extends TabViewBase {
const lastIndex = items.length - 1;
const offsideItems = this.androidTabsPosition === 'top' ? this.androidOffscreenTabLimit : 1;
let toUnload = [];
let toLoad = [];
const toUnload = [];
const toLoad = [];
iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i));
@ -623,7 +580,7 @@ export class TabView extends TabViewBase {
private disposeCurrentFragments(): void {
const fragmentManager = this._getFragmentManager();
const transaction = fragmentManager.beginTransaction();
let fragments = <Array<any>>fragmentManager.getFragments().toArray();
const fragments = <Array<any>>fragmentManager.getFragments().toArray();
for (let i = 0; i < fragments.length; i++) {
transaction.remove(fragments[i]);
}
@ -769,7 +726,7 @@ export class TabView extends TabViewBase {
return getDefaultAccentColor(this._context);
}
[androidSelectedTabHighlightColorProperty.setNative](value: number | Color) {
let tabLayout = this._tabLayout;
const tabLayout = this._tabLayout;
const color = value instanceof Color ? value.android : value;
tabLayout.setSelectedIndicatorColors([color]);
}