Skip to content

Commit 76e5d85

Browse files
committed
feat: getChildView working with templates
also prevent memory leaks
1 parent 49196e9 commit 76e5d85

File tree

3 files changed

+87
-53
lines changed

3 files changed

+87
-53
lines changed

src/ui-pager/index.android.ts

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
LOADMOREITEMS,
1010
Orientation,
1111
PagerBase,
12-
PagerItem,
1312
Transformer,
1413
autoPlayProperty,
1514
autoplayDelayProperty,
@@ -61,7 +60,9 @@ export class Pager extends PagerBase {
6160
private _pagerAdapter: PagerRecyclerAdapter;
6261
private _views: any[];
6362
private _pageListener: any;
64-
public _realizedItems = new Map<android.view.View, View>();
63+
// used to store viewHolder and thus their corresponding Views
64+
// used to "destroy" cells when possible
65+
_viewHolders = new Set<WeakRef<PagerViewHolder>>();
6566
public _childrenViewsType = new Map<number, View>();
6667
public _realizedTemplates = new Map<string, Map<android.view.View, View>>();
6768
lastEvent = 0;
@@ -163,6 +164,27 @@ export class Pager extends PagerBase {
163164
}
164165
}
165166

167+
private enumerateViewHolders<T = any>(cb: (v: PagerViewHolder) => T) {
168+
let result: T, v: PagerViewHolder;
169+
for (let it = this._viewHolders.values(), cellItemView: WeakRef<PagerViewHolder> = null; (cellItemView = it.next().value); ) {
170+
v = cellItemView?.get();
171+
if (v) {
172+
result = cb(v);
173+
if (result) {
174+
return result;
175+
}
176+
}
177+
}
178+
return result;
179+
}
180+
181+
getChildView(index: number): View {
182+
if (this._childrenViews) {
183+
return this._childrenViews[index].view;
184+
}
185+
return this.enumerateViewHolders<View>((v) => (v.getAdapterPosition() === index ? v.view : undefined));
186+
}
187+
166188
protected _removeChildView(index: number) {
167189
const type = this._childrenViews[index].type;
168190
this._childrenViewsType.delete(type);
@@ -309,11 +331,16 @@ export class Pager extends PagerBase {
309331
this._initAutoPlay(this.autoPlay);
310332
}
311333
};
312-
334+
disposeViewHolderViews() {
335+
this.enumerateViewHolders((v) => {
336+
this._removeViewCore(v.view);
337+
});
338+
this._viewHolders = new Set();
339+
}
313340
public disposeNativeView() {
314341
this.off(View.layoutChangedEvent, this.onLayoutChange, this);
315342
this._childrenViews = null;
316-
this._realizedItems.clear();
343+
this.disposeViewHolderViews();
317344
this._realizedTemplates.clear();
318345
this._pageListener = null;
319346
// setAdapter(null) will destroy views
@@ -465,13 +492,22 @@ export class Pager extends PagerBase {
465492
// this._android.setAdapter(null);
466493
super.onUnloaded();
467494
}
468-
469-
eachChildView(callback: (child: View) => boolean): void {
470-
if (this._realizedItems && this._realizedItems.size > 0) {
471-
this._realizedItems.forEach((view, key) => {
472-
callback(view);
473-
});
474-
}
495+
eachChild(callback: (child: ViewBase) => boolean) {
496+
super.eachChild(callback);
497+
// used for css updates (like theme change)
498+
this.enumerateViewHolders((v) => {
499+
const view = v.view;
500+
if (view) {
501+
if (view.parent instanceof Pager) {
502+
callback(view);
503+
} else {
504+
// in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined)
505+
if (view.parent) {
506+
callback(view.parent);
507+
}
508+
}
509+
}
510+
});
475511
}
476512

477513
updateAdapter() {
@@ -810,11 +846,10 @@ function initPagerRecyclerAdapter() {
810846
owner._addView(sp);
811847
sp.nativeView.setLayoutParams(new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.MATCH_PARENT));
812848

813-
owner._realizedItems.set(sp.nativeView, sp);
814-
815849
initPagerViewHolder();
816-
817-
return new PagerViewHolder(new WeakRef(sp), new WeakRef(owner));
850+
const holder = new PagerViewHolder(new WeakRef(sp), new WeakRef(owner));
851+
owner._viewHolders.add(new WeakRef(holder));
852+
return holder;
818853
}
819854

820855
getPosition(index: number): number {
@@ -1029,7 +1064,13 @@ function initStaticPagerStateAdapter() {
10291064
StaticPagerStateAdapter = StaticPagerStateAdapterImpl as any;
10301065
}
10311066

1032-
let PagerViewHolder;
1067+
interface PagerViewHolder extends androidx.recyclerview.widget.RecyclerView.ViewHolder {
1068+
// tslint:disable-next-line:no-misused-new
1069+
new (owner: WeakRef<View>, pager: WeakRef<Pager>): PagerViewHolder;
1070+
view: View;
1071+
}
1072+
// eslint-disable-next-line no-redeclare
1073+
let PagerViewHolder: PagerViewHolder;
10331074

10341075
function initPagerViewHolder() {
10351076
if (PagerViewHolder) {
@@ -1044,7 +1085,7 @@ function initPagerViewHolder() {
10441085
}
10451086

10461087
get view(): View {
1047-
return this.owner ? this.owner.get() : null;
1088+
return this.owner?.get();
10481089
}
10491090
}
10501091

@@ -1060,7 +1101,7 @@ function initZoomOutPageTransformer() {
10601101

10611102
@NativeClass
10621103
@Interfaces([androidx.viewpager2.widget.ViewPager2.PageTransformer])
1063-
class ZoomOutPageTransformerImpl extends androidx.viewpager2.widget.ViewPager2.PageTransformer {
1104+
class ZoomOutPageTransformerImpl extends java.lang.Object {
10641105
owner: WeakRef<Pager>;
10651106

10661107
constructor() {
@@ -1093,7 +1134,7 @@ function initZoomInPageTransformer() {
10931134

10941135
@NativeClass
10951136
@Interfaces([androidx.viewpager2.widget.ViewPager2.PageTransformer])
1096-
class ZoomInPageTransformerImpl extends androidx.viewpager2.widget.ViewPager2.PageTransformer {
1137+
class ZoomInPageTransformerImpl extends java.lang.Object {
10971138
owner: WeakRef<Pager>;
10981139

10991140
constructor() {

src/ui-pager/index.common.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export abstract class PagerBase extends ContainerView implements AddChildFromBui
114114
public transformers: string;
115115
public loadMoreCount: number = 1;
116116
public _childrenViews: { view: PagerItem; type: number }[];
117-
readonly abstract _childrenCount: number;
117+
abstract readonly _childrenCount: number;
118118
public disableSwipe: boolean = false;
119119
public showIndicator: boolean;
120120
public indicatorColor: Color | string;
@@ -477,9 +477,7 @@ disableSwipeProperty.register(PagerBase);
477477
export const perPageProperty = new Property<PagerBase, number>({
478478
name: 'perPage',
479479
defaultValue: 1,
480-
valueConverter: (value) =>{
481-
return Number(value);
482-
},
480+
valueConverter: (value) => Number(value)
483481
});
484482

485483
perPageProperty.register(PagerBase);

src/ui-pager/index.ios.ts

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
LOADMOREITEMS,
99
Orientation,
1010
PagerBase,
11-
PagerItem,
1211
autoPlayProperty,
1312
autoplayDelayProperty,
1413
disableSwipeProperty,
@@ -25,19 +24,6 @@ import {
2524
export * from './index.common';
2625
export { ItemsSource, Transformer } from './index.common';
2726

28-
function notifyForItemAtIndex(owner, nativeView: any, view: any, eventName: string, index: number) {
29-
const args = {
30-
eventName,
31-
object: owner,
32-
index,
33-
view,
34-
ios: nativeView,
35-
android: undefined
36-
};
37-
owner.notify(args);
38-
return args;
39-
}
40-
4127
const main_queue = dispatch_get_current_queue();
4228

4329
export enum ContentInsetAdjustmentBehavior {
@@ -162,6 +148,19 @@ export class Pager extends PagerBase {
162148
this._initAutoPlay(this.autoPlay);
163149
}
164150

151+
getChildView(index: number): View {
152+
if (this._childrenViews) {
153+
return this._childrenViews[index].view;
154+
}
155+
let result: View;
156+
if (this.nativeViewProtected) {
157+
const cell = this.mPager.cellForItemAtIndexPath(NSIndexPath.indexPathForRowInSection(index, 0)) as PagerCell;
158+
return cell?.view;
159+
}
160+
161+
return result;
162+
}
163+
165164
_getRealWidthHeight(): { width: number; height: number } {
166165
let height = 0;
167166
let width = 0;
@@ -315,7 +314,7 @@ export class Pager extends PagerBase {
315314
if (!view || size === 0) {
316315
return;
317316
}
318-
this._scrollToIndexAnimated(this.selectedIndex, false);
317+
this.scrollToIndexAnimated(this.selectedIndex, false);
319318
}
320319

321320
[selectedIndexProperty.setNative](value: number) {
@@ -454,7 +453,7 @@ export class Pager extends PagerBase {
454453

455454
_onItemsChanged(oldValue: any, newValue: any): void {}
456455

457-
_scrollToIndexAnimated(index: number, animate: boolean) {
456+
scrollToIndexAnimated(index: number, animate: boolean) {
458457
if (!this.pager) return;
459458

460459
const contentSize = this.pager.contentSize;
@@ -479,21 +478,17 @@ export class Pager extends PagerBase {
479478
return selectedIndexProperty.nativeValueChange(this, maxMinIndex);
480479
}
481480
}
482-
dispatch_async(main_queue, () => {
483-
if (this.mDataSource.collectionViewNumberOfItemsInSection(this.pager, 0) > maxMinIndex) {
484-
this.pager.scrollToItemAtIndexPathAtScrollPositionAnimated(
485-
NSIndexPath.indexPathForItemInSection(maxMinIndex, 0),
486-
this.orientation === 'vertical' ? UICollectionViewScrollPosition.CenteredVertically : UICollectionViewScrollPosition.CenteredHorizontally,
487-
!!animate
488-
);
489-
}
490-
491-
selectedIndexProperty.nativeValueChange(this, maxMinIndex);
492-
});
493-
}
481+
// dispatch_async(main_queue, () => {
482+
if (this.mDataSource.collectionViewNumberOfItemsInSection(this.pager, 0) > maxMinIndex) {
483+
this.pager.scrollToItemAtIndexPathAtScrollPositionAnimated(
484+
NSIndexPath.indexPathForItemInSection(maxMinIndex, 0),
485+
this.orientation === 'vertical' ? UICollectionViewScrollPosition.CenteredVertically : UICollectionViewScrollPosition.CenteredHorizontally,
486+
!!animate
487+
);
488+
}
494489

495-
public scrollToIndexAnimated(index: number, animate: boolean) {
496-
this._scrollToIndexAnimated(index, animate);
490+
selectedIndexProperty.nativeValueChange(this, maxMinIndex);
491+
// });
497492
}
498493

499494
@profile

0 commit comments

Comments
 (0)