Skip to content

Commit 044efaf

Browse files
committed
Fixed #568 - Possible memory leak when using Sticky Headers
Fixed #575 - Sticky header is disappearing when scrolling
1 parent 8f310f7 commit 044efaf

File tree

4 files changed

+26
-12
lines changed

4 files changed

+26
-12
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![Methods and Size](https://img.shields.io/badge/Methods%20and%20size-core:%201099%20|%20119%20KB-e91e63.svg)](http://www.methodscount.com/?lib=eu.davidea%3Aflexible-adapter%3A5.0.0%2B)
66

77
# FlexibleAdapter
8-
- [v5.0.2](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.2) built on 2018.03.17
8+
- [v5.0.3](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.3) built on 2018.03.23
99
- If you come from previous versions, update your code following the Wiki page [Migrations](https://github.com/davideas/FlexibleAdapter/wiki/Migrations).
1010
- Please read also [issues](https://github.com/davideas/FlexibleAdapter/issues) and [releases](https://github.com/davideas/FlexibleAdapter/releases).
1111

@@ -58,7 +58,7 @@ repositories {
5858
```
5959
dependencies {
6060
// Using JCenter
61-
compile 'eu.davidea:flexible-adapter:5.0.2'
61+
compile 'eu.davidea:flexible-adapter:5.0.3'
6262
compile 'eu.davidea:flexible-adapter-ui:1.0.0-b3'
6363
compile 'eu.davidea:flexible-adapter-livedata:1.0.0-b2'
6464
compile 'eu.davidea:flexible-adapter-databinding:1.0.0-b2'
@@ -70,7 +70,7 @@ dependencies {
7070
#### Stay Updated
7171
|Flexible Adapter|Live Data|Data Binding|UI|
7272
|---|---|---|---|
73-
|<div align="center">5.0.2</div>|<div align="center">1.0.0-b2</div>|<div align="center">1.0.0-b2</div>|<div align="center">1.0.0-b3</div>
73+
|<div align="center">5.0.3</div>|<div align="center">1.0.0-b2</div>|<div align="center">1.0.0-b2</div>|<div align="center">1.0.0-b3</div>
7474
|<a href='https://bintray.com/davideas/maven/flexible-adapter?source=watch' alt='Get automatic notifications about new "flexible-adapter" versions'><img src='https://www.bintray.com/docs/images/bintray_badge_color.png'></a>|<a href='https://bintray.com/davideas/maven/flexible-adapter-livedata?source=watch' alt='Get automatic notifications about new "flexible-adapter-livedata" versions'><img src='https://www.bintray.com/docs/images/bintray_badge_bw.png'></a>|<a href='https://bintray.com/davideas/maven/flexible-adapter-databinding?source=watch' alt='Get automatic notifications about new "flexible-adapter-databinding" versions'><img src='https://www.bintray.com/docs/images/bintray_badge_bw.png'></a>|<a href='https://bintray.com/davideas/maven/flexible-adapter-ui?source=watch' alt='Get automatic notifications about new "flexible-adapter-ui" versions'><img src='https://www.bintray.com/docs/images/bintray_badge_bw.png'></a>
7575

7676
# Wiki!
@@ -117,9 +117,10 @@ This [Wiki page](https://github.com/davideas/FlexibleAdapter/wiki/5.x-%7C-Demo-A
117117

118118
# Change Log
119119
###### Latest release
120-
[v5.0.2](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.2) - 2018.03.17
120+
[v5.0.3](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.3) - 2018.03.23
121121

122122
###### Old releases
123+
[v5.0.2](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.2) - 2018.03.17
123124
[v5.0.1](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.1) - 2018.03.11 |
124125
[v5.0.0](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.0) - 2018.03.04<br>
125126
[v5.0.0-rc4](https://github.com/davideas/FlexibleAdapter/releases/tag/5.0.0-rc4) - 2017.12.17 |

flexible-adapter/src/main/java/eu/davidea/flexibleadapter/FlexibleAdapter.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import android.support.v7.util.DiffUtil;
2929
import android.support.v7.widget.RecyclerView;
3030
import android.support.v7.widget.helper.ItemTouchHelper;
31-
import android.util.Log;
3231
import android.view.LayoutInflater;
3332
import android.view.MotionEvent;
3433
import android.view.View;
@@ -597,13 +596,14 @@ public void updateDataSet(@Nullable List<T> items) {
597596
* @see #setAnimateToLimit(int)
598597
* @see #onPostUpdate()
599598
* @since 5.0.0-b7 Created
600-
* <br>5.0.0-b8 Synchronization animations limit
601599
* <br>5.0.0-rc2 Copy of the Original List done internally
602600
*/
603601
@CallSuper
604602
public void updateDataSet(@Nullable List<T> items, boolean animate) {
605603
mOriginalList = null; // Reset original list from filter
606604
if (items == null) items = new ArrayList<>();
605+
// Always clear cache of bound view holders
606+
discardBoundViewHolders();
607607
if (animate) {
608608
mHandler.removeMessages(UPDATE);
609609
mHandler.sendMessage(Message.obtain(mHandler, UPDATE, items));
@@ -1769,10 +1769,11 @@ public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position,
17691769
item.bindViewHolder(this, holder, position, payloads);
17701770
// Avoid to show the double background in case header has transparency
17711771
// The visibility will be restored when header is reset in StickyHeaderHelper
1772-
if (areHeadersSticky() && !isFastScroll && mStickyHeaderHelper.getStickyPosition() >= 0 && payloads.isEmpty()) {
1772+
if (areHeadersSticky() && isHeader(item) && !isFastScroll && mStickyHeaderHelper.getStickyPosition() >= 0 && payloads.isEmpty()) {
17731773
int headerPos = getFlexibleLayoutManager().findFirstVisibleItemPosition() - 1;
1774-
if (headerPos == position && isHeader(item))
1774+
if (headerPos == position) {
17751775
holder.itemView.setVisibility(View.INVISIBLE);
1776+
}
17761777
}
17771778
}
17781779
// Endless Scroll
@@ -4236,7 +4237,7 @@ public FlexibleAdapter setDiffUtilCallback(DiffUtilCallback diffUtilCallback) {
42364237

42374238
private synchronized void animateDiff(@Nullable List<T> newItems, Payload payloadChange) {
42384239
if (useDiffUtil) {
4239-
Log.v(TAG, "Animate changes with DiffUtils! oldSize=" + getItemCount() + " newSize=" + newItems.size());
4240+
log.v("Animate changes with DiffUtils! oldSize=" + getItemCount() + " newSize=" + newItems.size());
42404241
if (diffUtilCallback == null) {
42414242
diffUtilCallback = new DiffUtilCallback();
42424243
}
@@ -4397,7 +4398,7 @@ private void applyAndAnimateMovedItems(List<T> from, List<T> newItems) {
43974398

43984399
private synchronized void executeNotifications(Payload payloadChange) {
43994400
if (diffResult != null) {
4400-
Log.i(TAG, "Dispatching notifications");
4401+
log.i("Dispatching notifications");
44014402
mItems = diffUtilCallback.getNewItems();// Update mItems in the UI Thread
44024403
diffResult.dispatchUpdatesTo(this);
44034404
diffResult = null;

flexible-adapter/src/main/java/eu/davidea/flexibleadapter/SelectableAdapter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,13 @@ public void onViewRecycled(RecyclerView.ViewHolder holder) {
503503
}
504504
}
505505

506+
/**
507+
* To call when views are all discarded.
508+
*/
509+
void discardBoundViewHolders() {
510+
mBoundViewHolders.clear();
511+
}
512+
506513
/**
507514
* Usually {@code RecyclerView} binds 3 items more than the visible items.
508515
*
@@ -555,6 +562,7 @@ public Set<Integer> getSelectedPositionsAsSet() {
555562
* @since 1.0.0
556563
*/
557564
public void onSaveInstanceState(Bundle outState) {
565+
discardBoundViewHolders();
558566
outState.putIntegerArrayList(TAG, new ArrayList<>(mSelectedPositions));
559567
if (getSelectedItemCount() > 0) log.d("Saving selection %s", mSelectedPositions);
560568
}

flexible-adapter/src/main/java/eu/davidea/flexibleadapter/helpers/StickyHeaderHelper.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,13 @@ private void translateHeader() {
235235
private void swapHeader(FlexibleViewHolder newHeader, int oldHeaderPosition) {
236236
if (mStickyHeaderViewHolder != null) {
237237
resetHeader(mStickyHeaderViewHolder);
238+
// #568, #575 - Header ViewHolder out of the top screen must be recycled manually
239+
if (mHeaderPosition > oldHeaderPosition) {
240+
mAdapter.onViewRecycled(mStickyHeaderViewHolder);
241+
}
238242
}
239243
mStickyHeaderViewHolder = newHeader;
240-
// mStickyHeaderViewHolder.setIsRecyclable(false);
244+
mStickyHeaderViewHolder.setIsRecyclable(false);
241245
ensureHeaderParent();
242246
onStickyHeaderChange(mHeaderPosition, oldHeaderPosition);
243247
}
@@ -300,7 +304,7 @@ private void resetHeader(FlexibleViewHolder header) {
300304
if (!header.itemView.equals(view)) {
301305
addViewToParent(((ViewGroup) header.itemView), view);
302306
}
303-
//header.setIsRecyclable(true);
307+
header.setIsRecyclable(true);
304308
// #294 - Expandable header is not resized / redrawn on automatic configuration change when sticky headers are enabled
305309
header.itemView.getLayoutParams().width = view.getLayoutParams().width;
306310
header.itemView.getLayoutParams().height = view.getLayoutParams().height;

0 commit comments

Comments
 (0)