mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-20 12:02:16 +02:00
Remove some unnecessary DB queries when legacy schema disabled
- collapsed + filtered status is included in the deck list from the backend, so does not need to be looked up for each row - cache the current deck id at deck list build time, so it doesn't need to be looked up for every row (applies to old schema too) - skip default deck logic, which is handled by backend
This commit is contained in:
parent
635a074472
commit
9644f5724c
@ -35,6 +35,7 @@ import com.ichi2.libanki.sched.Counts
|
||||
import com.ichi2.libanki.sched.TreeNode
|
||||
import com.ichi2.utils.KotlinCleanup
|
||||
import com.ichi2.utils.TypedFilter
|
||||
import net.ankiweb.rsdroid.BackendFactory
|
||||
import java.util.*
|
||||
|
||||
@KotlinCleanup("lots to do")
|
||||
@ -52,6 +53,7 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
private val mExpandImage: Drawable?
|
||||
private val mCollapseImage: Drawable?
|
||||
private val mNoExpander: Drawable = ColorDrawable(Color.TRANSPARENT)
|
||||
private var currentDeckId: Long = 0
|
||||
|
||||
// Listeners
|
||||
private var mDeckClickListener: View.OnClickListener? = null
|
||||
@ -129,6 +131,7 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
mNew = mLrn
|
||||
mNumbersComputed = true
|
||||
mHasSubdecks = false
|
||||
currentDeckId = mCol.decks.current().optLong("id")
|
||||
processNodes(nodes)
|
||||
// Filtering performs notifyDataSetChanged after the async work is complete
|
||||
getFilter().filter(filter)
|
||||
@ -185,7 +188,12 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
}
|
||||
// Set deck name and colour. Filtered decks have their own colour
|
||||
holder.deckName.text = node.lastDeckNameComponent
|
||||
if (mCol.decks.isDyn(node.did)) {
|
||||
val filtered = if (!BackendFactory.defaultLegacySchema) {
|
||||
node.filtered
|
||||
} else {
|
||||
mCol.decks.isDyn(node.did)
|
||||
}
|
||||
if (filtered) {
|
||||
holder.deckName.setTextColor(mDeckNameDynColor)
|
||||
} else {
|
||||
holder.deckName.setTextColor(mDeckNameDefaultColor)
|
||||
@ -218,7 +226,7 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
}
|
||||
|
||||
private fun isCurrentlySelectedDeck(node: AbstractDeckTreeNode): Boolean {
|
||||
return node.did == mCol.decks.current().optLong("id")
|
||||
return node.did == currentDeckId
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
@ -227,7 +235,11 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
|
||||
private fun setDeckExpander(expander: ImageButton, indent: ImageButton, node: TreeNode<AbstractDeckTreeNode>) {
|
||||
val nodeValue = node.value
|
||||
val collapsed = mCol.decks.get(nodeValue.did).optBoolean("collapsed", false)
|
||||
val collapsed = if (BackendFactory.defaultLegacySchema) {
|
||||
mCol.decks.get(nodeValue.did).optBoolean("collapsed", false)
|
||||
} else {
|
||||
node.value.collapsed
|
||||
}
|
||||
// Apply the correct expand/collapse drawable
|
||||
if (node.hasChildren()) {
|
||||
expander.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
||||
@ -249,20 +261,30 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
|
||||
private fun processNodes(nodes: List<TreeNode<AbstractDeckTreeNode>>) {
|
||||
for (node in nodes) {
|
||||
// If the default deck is empty, hide it by not adding it to the deck list.
|
||||
// We don't hide it if it's the only deck or if it has sub-decks.
|
||||
if (node.value.did == 1L && nodes.size > 1 && !node.hasChildren()) {
|
||||
if (!defaultDeckHasCards(mCol)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// If any of this node's parents are collapsed, don't add it to the deck list
|
||||
for (parent in mCol.decks.parents(node.value.did)) {
|
||||
mHasSubdecks = true // If a deck has a parent it means it's a subdeck so set a flag
|
||||
if (parent.optBoolean("collapsed")) {
|
||||
return
|
||||
var shouldRecurse = true
|
||||
if (BackendFactory.defaultLegacySchema) {
|
||||
// If the default deck is empty, hide it by not adding it to the deck list.
|
||||
// We don't hide it if it's the only deck or if it has sub-decks.
|
||||
if (node.value.did == 1L && nodes.size > 1 && !node.hasChildren()) {
|
||||
if (!defaultDeckHasCards(mCol)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// If any of this node's parents are collapsed, don't add it to the deck list
|
||||
for (parent in mCol.decks.parents(node.value.did)) {
|
||||
mHasSubdecks = true // If a deck has a parent it means it's a subdeck so set a flag
|
||||
if (parent.optBoolean("collapsed")) {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// backend takes care of excluding default, and includes collapsed info
|
||||
if (node.value.collapsed) {
|
||||
mHasSubdecks = true
|
||||
shouldRecurse = false
|
||||
}
|
||||
}
|
||||
|
||||
mDeckList.add(node)
|
||||
mCurrentDeckList.add(node)
|
||||
|
||||
@ -275,7 +297,9 @@ class DeckAdapter(private val layoutInflater: LayoutInflater, context: Context)
|
||||
}
|
||||
}
|
||||
// Process sub-decks
|
||||
processNodes(node.children)
|
||||
if (shouldRecurse) {
|
||||
processNodes(node.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,10 @@ abstract class AbstractDeckTreeNode(
|
||||
* @return The full deck name, e.g. "A::B::C"
|
||||
*/
|
||||
val fullDeckName: String,
|
||||
val did: Long
|
||||
val did: Long,
|
||||
// only set when new backend active
|
||||
open var collapsed: Boolean = false,
|
||||
open var filtered: Boolean = false
|
||||
) : Comparable<AbstractDeckTreeNode> {
|
||||
private val mNameComponents: Array<String>
|
||||
|
||||
|
@ -46,6 +46,8 @@ fun CollectionV16.deckTreeLegacy(includeCounts: Boolean): List<TreeNode<DeckDueT
|
||||
node.reviewCount,
|
||||
node.learnCount,
|
||||
node.newCount,
|
||||
collapsed = node.collapsed,
|
||||
filtered = node.filtered
|
||||
)
|
||||
)
|
||||
treeNode.children.addAll(node.childrenList.asSequence().map { toLegacyNode(it, thisName) })
|
||||
|
@ -36,7 +36,16 @@ import kotlin.math.min
|
||||
@KotlinCleanup("maybe possible to remove gettres for revCount/lrnCount")
|
||||
@KotlinCleanup("rename name -> fullDeckName")
|
||||
@RustCleanup("after migration, consider dropping this and using backend tree structure directly")
|
||||
class DeckDueTreeNode(name: String, did: Long, override var revCount: Int, override var lrnCount: Int, override var newCount: Int) : AbstractDeckTreeNode(name, did) {
|
||||
class DeckDueTreeNode(
|
||||
name: String,
|
||||
did: Long,
|
||||
override var revCount: Int,
|
||||
override var lrnCount: Int,
|
||||
override var newCount: Int,
|
||||
// only set when defaultLegacySchema is false
|
||||
override var collapsed: Boolean = false,
|
||||
override var filtered: Boolean = false
|
||||
) : AbstractDeckTreeNode(name, did, collapsed, filtered) {
|
||||
override fun toString(): String {
|
||||
return String.format(
|
||||
Locale.US, "%s, %d, %d, %d, %d",
|
||||
|
@ -242,7 +242,7 @@ public class Sched extends SchedV2 {
|
||||
// reviews
|
||||
int rev = _revForDeck(deck.getLong("id"), rlim);
|
||||
// save to list
|
||||
deckNodes.add(new DeckDueTreeNode(deck.getString("name"), deck.getLong("id"), rev, lrn, _new));
|
||||
deckNodes.add(new DeckDueTreeNode(deck.getString("name"), deck.getLong("id"), rev, lrn, _new, false, false));
|
||||
// add deck as a parent
|
||||
lims.put(Decks.normalizeName(deck.getString("name")), new Integer[]{nlim, rlim});
|
||||
}
|
||||
|
@ -563,7 +563,7 @@ public class SchedV2 extends AbstractSched {
|
||||
int rlim = _deckRevLimitSingle(deck, plim, false);
|
||||
int rev = _revForDeck(deck.getLong("id"), rlim, childMap);
|
||||
// save to list
|
||||
deckNodes.add(new DeckDueTreeNode(deck.getString("name"), deck.getLong("id"), rev, lrn, _new));
|
||||
deckNodes.add(new DeckDueTreeNode(deck.getString("name"), deck.getLong("id"), rev, lrn, _new, false, false));
|
||||
// add deck as a parent
|
||||
lims.put(Decks.normalizeName(deck.getString("name")), new Integer[]{nlim, rlim});
|
||||
}
|
||||
@ -593,8 +593,7 @@ public class SchedV2 extends AbstractSched {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@RustCleanup("enable for v2 once backend is updated to 2.1.41+")
|
||||
@RustCleanup("once both v1 and v2 are using backend, cancelListener can be removed")
|
||||
@RustCleanup("once defaultLegacySchema is removed, cancelListener can be removed")
|
||||
public List<TreeNode<DeckDueTreeNode>> deckDueTree(@Nullable CancelListener cancelListener) {
|
||||
if (!BackendFactory.getDefaultLegacySchema()) {
|
||||
return BackendSchedKt.deckTreeLegacy(getCol().getNewBackend(), true);
|
||||
|
@ -112,16 +112,16 @@ public class SchedV2Test extends RobolectricTest {
|
||||
// These matched the previous Java data
|
||||
// These may want to be changed back
|
||||
List<TreeNode<DeckDueTreeNode>> expected = new ArrayList<>();
|
||||
DeckDueTreeNode caz = new DeckDueTreeNode("cmxieunwoogyxsctnjmv::abcdefgh::ZYXW", 1596783600480L, 0, 0, 0);
|
||||
DeckDueTreeNode ca = new DeckDueTreeNode("cmxieunwoogyxsctnjmv::abcdefgh", 1596783600460L, 0, 0, 0);
|
||||
DeckDueTreeNode ci = new DeckDueTreeNode("cmxieunwoogyxsctnjmv::INSBGDS", 1596783600500L, 0, 0, 0);
|
||||
DeckDueTreeNode c = new DeckDueTreeNode("cmxieunwoogyxsctnjmv", 1596783600440L, 0, 0, 0);
|
||||
DeckDueTreeNode defaul = new DeckDueTreeNode("Default", 1, 0, 0, 0);
|
||||
DeckDueTreeNode s = new DeckDueTreeNode("scxipjiyozczaaczoawo", 1596783600420L, 0, 0, 0);
|
||||
DeckDueTreeNode f = new DeckDueTreeNode("blank::foobar", 1596783600540L, 0, 0, 0);
|
||||
DeckDueTreeNode b = new DeckDueTreeNode("blank", 1596783600520L, 0, 0, 0);
|
||||
DeckDueTreeNode aBlank = new DeckDueTreeNode("A::blank", 1596783600580L, 0, 0, 0);
|
||||
DeckDueTreeNode a = new DeckDueTreeNode("A", 1596783600560L, 0, 0, 0);
|
||||
DeckDueTreeNode caz = new DeckDueTreeNode("cmxieunwoogyxsctnjmv::abcdefgh::ZYXW", 1596783600480L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode ca = new DeckDueTreeNode("cmxieunwoogyxsctnjmv::abcdefgh", 1596783600460L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode ci = new DeckDueTreeNode("cmxieunwoogyxsctnjmv::INSBGDS", 1596783600500L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode c = new DeckDueTreeNode("cmxieunwoogyxsctnjmv", 1596783600440L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode defaul = new DeckDueTreeNode("Default", 1, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode s = new DeckDueTreeNode("scxipjiyozczaaczoawo", 1596783600420L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode f = new DeckDueTreeNode("blank::foobar", 1596783600540L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode b = new DeckDueTreeNode("blank", 1596783600520L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode aBlank = new DeckDueTreeNode("A::blank", 1596783600580L, 0, 0, 0, false, false);
|
||||
DeckDueTreeNode a = new DeckDueTreeNode("A", 1596783600560L, 0, 0, 0, false, false);
|
||||
|
||||
|
||||
TreeNode<DeckDueTreeNode> cazNode = new TreeNode<>(caz);
|
||||
|
Loading…
Reference in New Issue
Block a user