Skip to content

Commit

Permalink
Improved Performance and Added Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
prateek-singh-3212 committed Jun 5, 2022
1 parent 1117eef commit 5289b36
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 31 deletions.
7 changes: 1 addition & 6 deletions AnkiDroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ dependencies {
implementation 'com.drakeet.drawer:drawer:1.0.3'
implementation 'uk.co.samuelwall:material-tap-target-prompt:3.3.2'
implementation 'com.github.mrudultora:Colorpicker:1.2.0'
implementation "androidx.work:work-runtime-ktx:2.7.1"

// Cannot use debugImplementation since classes need to be imported in AnkiDroidApp
// and there's no no-op version for release build. Usage has been disabled for release
Expand Down Expand Up @@ -328,11 +329,5 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test:rules:1.4.0'

// GSON
implementation 'com.google.code.gson:gson:2.9.0'

// Work Manager
implementation "androidx.work:work-runtime-ktx:2.7.1"
}
apply from: "./kotlinMigration.gradle"
8 changes: 6 additions & 2 deletions AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -426,9 +426,9 @@ public static String getWebViewErrorMessage() {
* This function setups the work manager which run periodically.
**/
private void setupDeckMetaDataWorker() {
Timber.tag("META").e("Setting up deck meta data worker...");
Timber.d("Setting up deck meta data worker...");

PeriodicWorkRequest deckMetaDataWorker = new PeriodicWorkRequest.Builder(DeckMetaDataWorker.class, 2, TimeUnit.MINUTES)
PeriodicWorkRequest deckMetaDataWorker = new PeriodicWorkRequest.Builder(DeckMetaDataWorker.class, 30, TimeUnit.MINUTES)
.addTag(DeckMetaDataWorker.DECK_META_WORKER)
.build();

Expand All @@ -438,6 +438,10 @@ private void setupDeckMetaDataWorker() {
ExistingPeriodicWorkPolicy.REPLACE,
deckMetaDataWorker
);

// Does the required work in setting up new Worker.
String time = CollectionHelper.getInstance().getTimeSafe(this).getCurrentDate().toString();
DeckMetaDataWorker.Companion.setupNewWorker(this, time);
}


Expand Down
108 changes: 98 additions & 10 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckMetaDataPreference.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,129 @@ package com.ichi2.anki

import android.content.Context
import android.content.SharedPreferences
import com.google.gson.Gson
import androidx.core.content.edit
import com.ichi2.anki.worker.DeckMetaDataWorker
import com.ichi2.utils.JSONException
import com.ichi2.utils.JSONObject
import timber.log.Timber
import java.lang.NumberFormatException

class DeckMetaDataPreference(context: Context) {

private val sharedPreferences: SharedPreferences =
context.getSharedPreferences("DeckMetaData", Context.MODE_PRIVATE)

/**
* Use this to store data in shared preference.
* @param key The Key of value. Used in fetching the data.
* @param value Value that needs to be stored <b>(VALUE MUST BE STRING)</b>.
* */
fun putString(key: String, value: String) {
sharedPreferences.edit()
.putString(key, value)
.apply()
sharedPreferences.edit {
putString(key, value)
apply()
}
}

/**
* Use this to fetch string from shared preference.
* @prams The Key of deck whose data you want to fetch.
* @return Value that needs to be fetched <b>(VALUE WILL BE STRING)</b>.
* */
fun getString(key: String, default: String): String {
return sharedPreferences.getString(key, default)!!
}

/**
* Use this to store int in shared preference.
* @param key The Key of value. Created while storing the data.
* @param value Value that needs to be stored <b>(VALUE MUST BE INTEGER)</b>.
* */
fun putInt(key: String, value: Int) {
sharedPreferences.edit {
putInt(key, value)
apply()
}
}

/**
* Use this to fetch integer from shared preference.
* @prams The Key of deck whose data you want to fetch.
* @return Value that needs to be fetched <b>(VALUE WILL BE INTEGER)</b>.
* */
fun getInt(key: String, default: Int): Int {
return sharedPreferences.getInt(key, default)
}

/**
* Use this to store meta data in shared preference.
* @param key The Key of deck whose data you want to fetch. (deck id is the for deck)
* @param value Object of Metadata Model
* */
fun setMetaData(key: String, value: DeckMetaDataWorker.Meta) {
val json: String = Gson().toJson(value)
sharedPreferences.edit()
.putString(key, json)
.apply()
Timber.tag("META").e(json)
val jsonObject = JSONObject()

try {
jsonObject.put("did", value.did)
jsonObject.put("deckName", value.deckName)
jsonObject.put("new", value.new)
jsonObject.put("lrn", value.lrn)
jsonObject.put("rev", value.rev)
jsonObject.put("eta", value.eta)
} catch (e: JSONException) {
Timber.d(e)
return
}

val json = jsonObject.toString()

sharedPreferences.edit {
putString(key, json)
apply()
}
}

/**
* Use this to fetch meta data from shared preference if Deck ID (did) is known.
* @prams The Key of deck whose data you want to fetch. (deck id is the for deck)
* @return Object of Metadata Model.
* */
fun getMetaData(key: String): DeckMetaDataWorker.Meta? {
val jsonData = sharedPreferences
.getString(key, null)

return if (jsonData == null) {
null
} else {
Gson().fromJson(jsonData, DeckMetaDataWorker.Meta::class.java)
val jsonObject = JSONObject(jsonData)
return DeckMetaDataWorker.Meta(
jsonObject.getLong("did"),
jsonObject.getString("deckName"),
jsonObject.getInt("new"),
jsonObject.getInt("lrn"),
jsonObject.getInt("rev"),
jsonObject.getInt("eta"),
)
}
}

/**
* Use this to fetch all meta data from shared preference.
* @return List of all Meta Data Object.
* */
fun getAllMetaData(): List<DeckMetaDataWorker.Meta> {
val listMeta = mutableListOf<DeckMetaDataWorker.Meta>()
val dids = sharedPreferences.all.keys.filter { data -> data.isLong() }
dids.forEach {
listMeta.add(getMetaData(it)!!)
}
return listMeta
}

private fun String.isLong(): Boolean = try {
this.toLong()
true
} catch (e: NumberFormatException) {
false
}
}
45 changes: 33 additions & 12 deletions AnkiDroid/src/main/java/com/ichi2/anki/worker/DeckMetaDataWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import androidx.work.Worker
import androidx.work.WorkerParameters
import com.ichi2.anki.CollectionHelper
import com.ichi2.anki.DeckMetaDataPreference
import com.ichi2.libanki.Collection
import com.ichi2.libanki.sched.Counts
import com.ichi2.libanki.sched.DeckDueTreeNode
import timber.log.Timber

/**
Expand All @@ -31,41 +33,51 @@ import timber.log.Timber
* */
class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameters) : Worker(context, workerParameters) {

private lateinit var colHelper: CollectionHelper
// Lambda to check the collection is not null.
private val mCollection: (context: Context) -> Collection? = {
val collection = CollectionHelper.getInstance()
if (collection.getColSafe(it) != null) {
collection.getCol(it)
} else {
null
}
}

override fun doWork(): Result {

colHelper = CollectionHelper.getInstance()
val date = CollectionHelper.getInstance().getTimeSafe(context).currentDate

Timber.tag("META").e("Deck Meta Data Worker started at: ${colHelper.getTimeSafe(context).currentDate}")
Timber.d("Deck Meta Data Worker started at: $date")

// Update the data of Deck Metadata from HERE
val col = colHelper.getCol(context)
val deckList = col.sched.deckDueList()
val sched = mCollection(context)?.sched ?: return Result.failure()
val deckList: List<DeckDueTreeNode> = sched.deckDueList()

deckList.forEach {
val new = it?.newCount ?: -1
val lrn = it?.lrnCount ?: -1
val rev = it?.revCount ?: -1
val new = it.newCount
val lrn = it.lrnCount
val rev = it.revCount
val data = Meta(
it?.did ?: -1,
it?.fullDeckName ?: "Deck Name",
it.did,
it.fullDeckName,
new,
lrn,
rev,
col.sched.eta(Counts(new, lrn, rev), false)
sched.eta(Counts(new, lrn, rev), false)
)
storeInPreference(data)
}

updateLastFetch(colHelper.getTimeSafe(context).toString())
updateLastFetch(date.toString())

return Result.success() // Done work successfully...
}

private fun updateLastFetch(time: String) {
val metaPreference = DeckMetaDataPreference(context)
metaPreference.putString(LAST_FETCH_TIME, time)
val prevData = metaPreference.getInt(TIMES_FETCHED, 0)
metaPreference.putInt(TIMES_FETCHED, prevData + 1)
}

/**
Expand All @@ -88,5 +100,14 @@ class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameter
companion object {
const val DECK_META_WORKER = "DeckMetaData"
const val LAST_FETCH_TIME = "LAST_FETCH"
const val TIMES_FETCHED = "TIMES_FETCHED"
const val WORKER_CREATED = "WORKER_CREATED"

fun setupNewWorker(context: Context, time: String) {
Timber.d("Setting up Preference for new Worker.")
val metaDataPreference = DeckMetaDataPreference(context)
metaDataPreference.putString(WORKER_CREATED, time)
metaDataPreference.putInt(TIMES_FETCHED, 0)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ abstract class AbstractSched {
/**
* @return [deckname, did, rev, lrn, new]
*/
abstract fun deckDueList(): List<DeckDueTreeNode?>
abstract fun deckDueList(): List<DeckDueTreeNode>

/**
* @param cancelListener A task that is potentially cancelled
Expand Down

0 comments on commit 5289b36

Please sign in to comment.