Save scrolling position in LRU cache

This commit is contained in:
Adrian Ulrich 2015-09-23 09:33:47 +02:00
parent 1d9cc03105
commit 83c037d1de
2 changed files with 40 additions and 57 deletions

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2012 Christopher Eby <kreed@kreed.org> * Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
* Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -732,7 +733,7 @@ public class LibraryActivity
.setMessage(delete_message) .setMessage(delete_message)
.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
mPagerAdapter.maintainState(); // remember current scrolling position mPagerAdapter.maintainPosition(); // remember current scrolling position
mHandler.sendMessage(mHandler.obtainMessage(MSG_DELETE, intent)); mHandler.sendMessage(mHandler.obtainMessage(MSG_DELETE, intent));
} }
}) })

View File

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2012 Christopher Eby <kreed@kreed.org> * Copyright (C) 2012 Christopher Eby <kreed@kreed.org>
* Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -118,9 +119,9 @@ public class LibraryPagerAdapter
*/ */
private FileSystemAdapter mFilesAdapter; private FileSystemAdapter mFilesAdapter;
/** /**
* LRU cache holding the last scrolling position of the filesadapter listview * LRU cache holding the last scrolling position of all adapter views
*/ */
private FilePositionLruCache mFilePosLRU; private static AdaperPositionLruCache sLruAdapterPos;
/** /**
* The adapter of the currently visible list. * The adapter of the currently visible list.
*/ */
@ -141,10 +142,6 @@ public class LibraryPagerAdapter
* A limiter that should be set when the files adapter is created. * A limiter that should be set when the files adapter is created.
*/ */
private Limiter mPendingFileLimiter; private Limiter mPendingFileLimiter;
/**
* List positions stored in the saved state, or null if none were stored.
*/
private int[] mSavedPositions;
/** /**
* The LibraryActivity that owns this adapter. The adapter will be notified * The LibraryActivity that owns this adapter. The adapter will be notified
* of changes in the current page. * of changes in the current page.
@ -206,7 +203,8 @@ public class LibraryPagerAdapter
*/ */
public LibraryPagerAdapter(LibraryActivity activity, Looper workerLooper) public LibraryPagerAdapter(LibraryActivity activity, Looper workerLooper)
{ {
mFilePosLRU = new FilePositionLruCache(32); if (sLruAdapterPos == null)
sLruAdapterPos = new AdaperPositionLruCache(32);
mActivity = activity; mActivity = activity;
mUiHandler = new Handler(this); mUiHandler = new Handler(this);
mWorkerHandler = new Handler(workerLooper, this); mWorkerHandler = new Handler(workerLooper, this);
@ -426,7 +424,6 @@ public class LibraryPagerAdapter
mPendingAlbumLimiter = (Limiter)in.getSerializable("limiter_albums"); mPendingAlbumLimiter = (Limiter)in.getSerializable("limiter_albums");
mPendingSongLimiter = (Limiter)in.getSerializable("limiter_songs"); mPendingSongLimiter = (Limiter)in.getSerializable("limiter_songs");
mPendingFileLimiter = (Limiter)in.getSerializable("limiter_files"); mPendingFileLimiter = (Limiter)in.getSerializable("limiter_files");
mSavedPositions = in.getIntArray("pos");
} }
@Override @Override
@ -439,30 +436,10 @@ public class LibraryPagerAdapter
out.putSerializable("limiter_songs", mSongAdapter.getLimiter()); out.putSerializable("limiter_songs", mSongAdapter.getLimiter());
if (mFilesAdapter != null) if (mFilesAdapter != null)
out.putSerializable("limiter_files", mFilesAdapter.getLimiter()); out.putSerializable("limiter_files", mFilesAdapter.getLimiter());
maintainPosition();
int[] savedPositions = new int[MAX_ADAPTER_COUNT];
ListView[] lists = mLists;
for (int i = MAX_ADAPTER_COUNT; --i != -1; ) {
if (lists[i] != null) {
savedPositions[i] = lists[i].getFirstVisiblePosition();
}
}
out.putIntArray("pos", savedPositions);
return out; return out;
} }
/**
* Forcefully updates mSavedPositions by storing the current
* state and passing it back into restoreState()
* This ensures that the nest MSG_COMMIT_QUERY will
* keep the current scrolling position
*/
public void maintainState()
{
Parcelable state = saveState();
restoreState(state, null);
}
/** /**
* Sets the text to be displayed in the first row of the artist, album, and * Sets the text to be displayed in the first row of the artist, album, and
* song lists. * song lists.
@ -485,6 +462,8 @@ public class LibraryPagerAdapter
*/ */
public void clearLimiter(int type) public void clearLimiter(int type)
{ {
maintainPosition();
if (type == MediaUtils.TYPE_FILE) { if (type == MediaUtils.TYPE_FILE) {
if (mFilesAdapter == null) { if (mFilesAdapter == null) {
mPendingFileLimiter = null; mPendingFileLimiter = null;
@ -520,6 +499,8 @@ public class LibraryPagerAdapter
{ {
int tab; int tab;
maintainPosition();
switch (limiter.type) { switch (limiter.type) {
case MediaUtils.TYPE_ALBUM: case MediaUtils.TYPE_ALBUM:
if (mSongAdapter == null) { if (mSongAdapter == null) {
@ -571,10 +552,6 @@ public class LibraryPagerAdapter
if (mFilesAdapter == null) { if (mFilesAdapter == null) {
mPendingFileLimiter = limiter; mPendingFileLimiter = limiter;
} else { } else {
Limiter oldLimiter = mFilesAdapter.getLimiter();
int curPos = mLists[limiter.type].getFirstVisiblePosition();
mFilePosLRU.putLimiter(oldLimiter, curPos);
mFilesAdapter.setLimiter(limiter); mFilesAdapter.setLimiter(limiter);
requestRequery(mFilesAdapter); requestRequery(mFilesAdapter);
} }
@ -587,6 +564,17 @@ public class LibraryPagerAdapter
return tab; return tab;
} }
/**
* Saves the scrolling position of every visible limiter
*/
public void maintainPosition() {
for (int i = MAX_ADAPTER_COUNT; --i != -1; ) {
if (mAdapters[i] != null) {
sLruAdapterPos.storePosition(mAdapters[i], mLists[i].getFirstVisiblePosition());
}
}
}
/** /**
* Returns the limiter set on the current adapter or null if there is none. * Returns the limiter set on the current adapter or null if there is none.
*/ */
@ -637,22 +625,14 @@ public class LibraryPagerAdapter
break; break;
} }
case MSG_COMMIT_QUERY: { case MSG_COMMIT_QUERY: {
int pos = 0;
int index = message.arg1; int index = message.arg1;
mAdapters[index].commitQuery(message.obj); mAdapters[index].commitQuery(message.obj);
int pos;
if (mSavedPositions == null) {
pos = 0;
} else {
pos = mSavedPositions[index];
mSavedPositions[index] = 0;
}
if (index == MediaUtils.TYPE_FILE) { Limiter curLimiter = mAdapters[index].getLimiter();
Limiter curLimiter = mAdapters[index].getLimiter(); Integer curPos = sLruAdapterPos.getPosition(mAdapters[index]);
Integer curPos = mFilePosLRU.getLimiter(curLimiter); if (curPos != null)
if (curPos != null) pos = (int)curPos;
pos = (int)curPos;
}
mLists[index].setSelection(pos); mLists[index].setSelection(pos);
break; break;
@ -848,24 +828,26 @@ public class LibraryPagerAdapter
} }
/** /**
* LRU implementation for filebrowser position cache * LRU implementation: saves the adapter position
*/ */
private class FilePositionLruCache extends LruCache<String, Integer> { private class AdaperPositionLruCache extends LruCache<String, Integer> {
public FilePositionLruCache(int size) { public AdaperPositionLruCache(int size) {
super(size); super(size);
} }
public void putLimiter(Limiter limiter, Integer val) { public void storePosition(LibraryAdapter adapter, Integer val) {
this.put(_k(limiter), val); this.put(_k(adapter), val);
} }
public Integer getLimiter(Limiter limiter) { public Integer getPosition(LibraryAdapter adapter) {
return this.get(_k(limiter)); return this.get(_k(adapter));
} }
/** /**
* Stringify limiter or return / if null * Assemble internal cache key from adapter
*/ */
private String _k(Limiter limiter) { private String _k(LibraryAdapter adapter) {
String result = "/"; String result = adapter.getMediaType()+"://";
Limiter limiter = adapter.getLimiter();
if (limiter != null) { if (limiter != null) {
for(String entry : limiter.names) { for(String entry : limiter.names) {
result = result + entry + "/"; result = result + entry + "/";