Skip to content

Commit

Permalink
Add ViewHolderCache
Browse files Browse the repository at this point in the history
  • Loading branch information
TellH committed Jan 22, 2017
1 parent 8e66e25 commit c773605
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 73 deletions.
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -16,8 +16,6 @@

public class MainActivity extends AppCompatActivity {
private RecyclerView rv;
private LinearLayoutManager linearLayoutManager;
private StickyHeaderView stickyHeaderView;
private StickyHeaderViewAdapter adapter;

@Override
Expand Down Expand Up @@ -58,8 +56,7 @@ public int compare(User o1, User o2) {

private void initView() {
rv = (RecyclerView) findViewById(R.id.recyclerView);
stickyHeaderView = (StickyHeaderView) findViewById(R.id.stickyHeaderView);
linearLayoutManager = new LinearLayoutManager(this);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(linearLayoutManager);
}

Expand All @@ -73,11 +70,10 @@ public boolean onCreateOptionsMenu(Menu menu) {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add_view:
// stickyHeaderView.clearHeaderView();
// stickyHeaderView.updateHeaderView(R.layout.header, entity, position);
break;
case R.id.action_remove_view:
stickyHeaderView.clearHeaderView();
User user = new User("Sticky View", 123, "https://avatars.githubusercontent.com/u/15800681?v=3");
user.setShouldSticky(true);
adapter.getDisplayList().add(3, user);
adapter.notifyItemInserted(3);
break;
default:
break;
Expand Down
Expand Up @@ -5,6 +5,7 @@
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -26,6 +27,7 @@ public class StickyHeaderView extends FrameLayout {
private StickyHeaderViewAdapter adapter;
private LinearLayoutManager layoutManager;
private Stack<Integer> stickyHeaderPositionStack = new Stack<>();
private LruCache<Integer, RecyclerView.ViewHolder> mViewHolderCache;

public StickyHeaderView(Context context) {
super(context);
Expand Down Expand Up @@ -53,54 +55,61 @@ private void initView() {
mHeaderContainer.setLayoutParams(
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
addView(mHeaderContainer);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (mHeaderHeight == -1 || mHeaderHeight == 0 || adapter == null || layoutManager == null) {
mHeaderHeight = mHeaderContainer.getHeight();
adapter = (StickyHeaderViewAdapter) mRecyclerView.getAdapter();
layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
if (adapter != null)
stickyHeaderPositionStack.push(findFirstVisibleStickyHeaderPosition(adapter.displayList, 0));
}
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mHeaderHeight == -1 || adapter == null || layoutManager == null)
return;
List<DataBean> displayList = adapter.getDisplayList();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
int firstVisibleStickyHeaderPosition = findFirstVisibleStickyHeaderPosition(displayList, firstVisibleItemPosition);
int currentStickyHeaderPosition = stickyHeaderPositionStack.peek();
if (firstVisibleStickyHeaderPosition - firstVisibleItemPosition > 1) {
return;
}
View firstVisibleStickyHeader = layoutManager.findViewByPosition(firstVisibleStickyHeaderPosition);
if (firstVisibleStickyHeader == null)
return;
int headerTop = firstVisibleStickyHeader.getTop();
if (headerTop > 0 && headerTop <= mHeaderHeight) {
mHeaderContainer.setY(-(mHeaderHeight - headerTop));
if (firstVisibleStickyHeaderPosition == currentStickyHeaderPosition) {
stickyHeaderPositionStack.pop();
if (!stickyHeaderPositionStack.isEmpty())
updateHeaderView(stickyHeaderPositionStack.peek());
mRecyclerView.addOnScrollListener(
new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (mHeaderHeight == -1 || mHeaderHeight == 0 || adapter == null || layoutManager == null) {
mHeaderHeight = mHeaderContainer.getHeight();
adapter = (StickyHeaderViewAdapter) mRecyclerView.getAdapter();
layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
if (adapter != null) {
mViewHolderCache = new LruCache<>(adapter.getItemCount() / 3);
}
}
}
} else if (headerTop <= 0) {
mHeaderContainer.setY(0);
updateHeaderView(firstVisibleItemPosition);
}

// Cache the StickyHeader position.
if (firstVisibleStickyHeaderPosition > currentStickyHeaderPosition)
stickyHeaderPositionStack.push(firstVisibleStickyHeaderPosition);
else if (firstVisibleStickyHeaderPosition < currentStickyHeaderPosition)
stickyHeaderPositionStack.pop();
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mHeaderHeight == -1 || adapter == null || layoutManager == null)
return;
List<DataBean> displayList = adapter.getDisplayList();
if (stickyHeaderPositionStack.isEmpty())
stickyHeaderPositionStack.push(findFirstVisibleStickyHeaderPosition(adapter.displayList, 0));
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
int firstVisibleStickyHeaderPosition = findFirstVisibleStickyHeaderPosition(displayList, firstVisibleItemPosition);
int currentStickyHeaderPosition = stickyHeaderPositionStack.peek();
if (firstVisibleStickyHeaderPosition - firstVisibleItemPosition > 1) {
return;
}
// 如果两个连续两个都是StickyView, 取下面那个View
if (displayList.get(firstVisibleStickyHeaderPosition + 1).shouldSticky())
firstVisibleStickyHeaderPosition++;
View firstVisibleStickyHeader = layoutManager.findViewByPosition(firstVisibleStickyHeaderPosition);
if (firstVisibleStickyHeader == null)
return;
int headerTop = firstVisibleStickyHeader.getTop();
if (headerTop > 0 && headerTop <= mHeaderHeight) {
mHeaderContainer.setY(-(mHeaderHeight - headerTop));
if (firstVisibleStickyHeaderPosition == currentStickyHeaderPosition) {
stickyHeaderPositionStack.pop();
if (!stickyHeaderPositionStack.isEmpty())
updateHeaderView(stickyHeaderPositionStack.peek());
}
} else if (headerTop <= 0) {
mHeaderContainer.setY(0);
updateHeaderView(firstVisibleItemPosition);
}

// Cache the StickyHeader position.
if (firstVisibleStickyHeaderPosition > currentStickyHeaderPosition)
stickyHeaderPositionStack.push(firstVisibleStickyHeaderPosition);
else if (firstVisibleStickyHeaderPosition < currentStickyHeaderPosition)
stickyHeaderPositionStack.pop();
}
}
}

);

Expand All @@ -116,19 +125,24 @@ private int findFirstVisibleStickyHeaderPosition(List<DataBean> displayList, int
return i;
}

public void updateHeaderView(int position) {
private void updateHeaderView(int position) {
DataBean entity = adapter.getDisplayList().get(position);
int layoutId = entity.getItemLayoutId(adapter);
clearHeaderView();
View v = LayoutInflater.from(mHeaderContainer.getContext())
.inflate(layoutId, mHeaderContainer, false);
mHeaderContainer.addView(v);
mHeaderHeight = mHeaderContainer.getHeight();
RecyclerView.ViewHolder viewHolder = mViewHolderCache.get(layoutId);
ViewBinder headerViewBinder = adapter.getViewBinder(layoutId);
headerViewBinder.bindView(adapter, headerViewBinder.provideViewHolder(v), position, entity);
if (viewHolder == null) {
View v = LayoutInflater.from(mHeaderContainer.getContext())
.inflate(layoutId, mHeaderContainer, false);
viewHolder = headerViewBinder.provideViewHolder(v);
mViewHolderCache.put(layoutId, viewHolder);
}
mHeaderContainer.addView(viewHolder.itemView);
mHeaderHeight = mHeaderContainer.getHeight();
headerViewBinder.bindView(adapter, viewHolder, position, entity);
}

public void clearHeaderView() {
private void clearHeaderView() {
mHeaderContainer.removeAllViews();
}

Expand Down
18 changes: 15 additions & 3 deletions app/src/main/java/tellh/com/recyclerstickyheaderview/User.java
Expand Up @@ -4,6 +4,16 @@ public class User extends DataBean {
private String login;
private int id;
private String avatar_url;
private boolean shouldSticky;

public User() {
}

public User(String login, int id, String avatar_url) {
this.login = login;
this.id = id;
this.avatar_url = avatar_url;
}

public String getAvatar_url() {
return avatar_url;
Expand Down Expand Up @@ -34,11 +44,13 @@ public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.item_user;
}

public void setShouldSticky(boolean shouldSticky) {
this.shouldSticky = shouldSticky;
}

@Override
protected boolean shouldSticky() {
if (id == 1269143)
return true;
return super.shouldSticky();
return shouldSticky;
}

public static String dataSource = "{\"items\": [\n" +
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/header.xml
Expand Up @@ -11,5 +11,5 @@
android:layout_height="wrap_content"
android:gravity="center"
tools:text="H"
android:textSize="20sp" />
android:textSize="26sp" />
</FrameLayout>
4 changes: 2 additions & 2 deletions app/src/main/res/layout/item_user.xml
Expand Up @@ -16,8 +16,8 @@

<ImageView
android:id="@+id/iv_avatar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
tools:src="@mipmap/ic_launcher" />

Expand Down
8 changes: 2 additions & 6 deletions app/src/main/res/menu/menu_main.xml
@@ -1,9 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">

<item android:title="Add view"
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Add Sticky view"
android:id="@+id/action_add_view" />
<item android:title="Remove view"
android:id="@+id/action_remove_view" />
</menu>

0 comments on commit c773605

Please sign in to comment.