Skip to content

Commit 98b25ac

Browse files
Fixes Issue 5933: Nearby: Display of all nearby pins makes the app sluggish, leads to crashes (commons-app#6181)
* Place.java: change getWikiDataEntityID() method to increase speed Before this commit, this method would perform the String replace method on the Wikidata link every time getWikiDataEntityID() was called. Also, getWikiDataLink() was called. This caused poor performance since both method calls are slow. This commit changes the method to only run the slow methods if the entityID field is empty or null. Once the field is populated, the method simply returns the field. This change allows getWikiDataEntityID() to run much faster. * NearbyParentFragmentPresenter.kt: change async and place update parameters Before this commit, the parameters that configure the async and place update code contributed to the slow loading of the red and green map markers. This commit changes the parameters such that the red and green map markers load much faster. These parameters may need further tuning. This commit's changes are simply an educated guess at a good parameter set. * NearbyParentFragment.kt: rewrite Java Drawable caching code to Kotlin Before this commit, the code which cached Drawables was written in Java. This commit rewrites that code into the new Kotlin file, which replaces the Java file. * NearbyParentFragmentPresenter.kt: change loadPlacesDataAsync to retry HTTP requests after failure Before this commit, when an HTTP request failed, the entire batch of Places would not get updated, even if it was only one Place in the batch that caused the failure. This commit changes the code such that upon HTTP request failure, new HTTP requests are sent with one Place per request. This allows more Places to be fetched from the server.
1 parent 40241b4 commit 98b25ac

File tree

3 files changed

+73
-13
lines changed

3 files changed

+73
-13
lines changed

app/src/main/java/fr/free/nrw/commons/nearby/Place.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,23 @@ public void setDistance(String distance) {
232232
*/
233233
@Nullable
234234
public String getWikiDataEntityId() {
235+
if (this.entityID != null && !this.entityID.equals("")) {
236+
return this.entityID;
237+
}
238+
235239
if (!hasWikidataLink()) {
236240
Timber.d("Wikidata entity ID is null for place with sitelink %s", siteLinks.toString());
237241
return null;
238242
}
239243

244+
//Determine entityID from link
240245
String wikiDataLink = siteLinks.getWikidataLink().toString();
241-
return wikiDataLink.replace("http://www.wikidata.org/entity/", "");
246+
247+
if (wikiDataLink.contains("http://www.wikidata.org/entity/")) {
248+
this.entityID = wikiDataLink.substring("http://www.wikidata.org/entity/".length());
249+
return this.entityID;
250+
}
251+
return null;
242252
}
243253

244254
/**

app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.content.IntentFilter
1111
import android.content.res.Configuration
1212
import android.graphics.Color
1313
import android.graphics.Paint
14+
import android.graphics.drawable.Drawable
1415
import android.location.Location
1516
import android.location.LocationManager
1617
import android.net.Uri
@@ -219,6 +220,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), NearbyParentFragmen
219220

220221
@Volatile
221222
private var stopQuery = false
223+
private var drawableCache: MutableMap<Pair<Context, Int>, Drawable>? = null
222224

223225
// Explore map data (for if we came from Explore)
224226
private var prevZoom = 0.0
@@ -721,6 +723,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), NearbyParentFragmen
721723
startMapWithoutPermission()
722724
}
723725
}
726+
drawableCache = HashMap()
724727
}
725728

726729
/**
@@ -1501,7 +1504,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), NearbyParentFragmen
15011504
marker.showInfoWindow()
15021505
presenter!!.handlePinClicked(updatedPlace)
15031506
savePlaceToDatabase(place)
1504-
val icon = ContextCompat.getDrawable(
1507+
val icon = getDrawable(
15051508
requireContext(),
15061509
getIconFor(updatedPlace, isBookMarked)
15071510
)
@@ -2027,8 +2030,35 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), NearbyParentFragmen
20272030
)
20282031
}
20292032

2033+
/**
2034+
* Gets the specified Drawable object. This is a wrapper method for ContextCompat.getDrawable().
2035+
* This method caches results from previous calls for faster retrieval.
2036+
*
2037+
* @param context The context to use to get the Drawable
2038+
* @param id The integer that describes the Drawable resource
2039+
* @return The Drawable object
2040+
*/
2041+
private fun getDrawable(context: Context?, id: Int?): Drawable? {
2042+
if (drawableCache == null || context == null || id == null) {
2043+
return null
2044+
}
2045+
2046+
val key = Pair(context, id)
2047+
if (!drawableCache!!.containsKey(key)) {
2048+
val drawable = ContextCompat.getDrawable(context, id)
2049+
2050+
if (drawable != null) {
2051+
drawableCache!![key] = drawable
2052+
} else {
2053+
return null
2054+
}
2055+
}
2056+
2057+
return drawableCache!![key]
2058+
}
2059+
20302060
fun convertToMarker(place: Place, isBookMarked: Boolean): Marker {
2031-
val icon = ContextCompat.getDrawable(requireContext(), getIconFor(place, isBookMarked))
2061+
val icon = getDrawable(requireContext(), getIconFor(place, isBookMarked))
20322062
val point = GeoPoint(place.location.latitude, place.location.longitude)
20332063
val marker = Marker(binding!!.map)
20342064
marker.position = point
@@ -2430,7 +2460,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), NearbyParentFragmen
24302460
Marker.ANCHOR_BOTTOM
24312461
)
24322462
startMarker.icon =
2433-
ContextCompat.getDrawable(
2463+
getDrawable(
24342464
this.requireContext(),
24352465
fr.free.nrw.commons.R.drawable.current_location_marker
24362466
)
@@ -2488,7 +2518,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), NearbyParentFragmen
24882518
Marker(binding?.map).apply {
24892519
position = it
24902520
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
2491-
icon = ContextCompat.getDrawable(context, R.drawable.current_location_marker)
2521+
icon = getDrawable(context, R.drawable.current_location_marker)
24922522
title = "Your Location"
24932523
textLabelFontSize = 24
24942524
overlays.add(this)

app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ import kotlinx.coroutines.Job
2525
import kotlinx.coroutines.channels.Channel
2626
import kotlinx.coroutines.delay
2727
import kotlinx.coroutines.ensureActive
28+
import kotlinx.coroutines.job
2829
import kotlinx.coroutines.launch
2930
import kotlinx.coroutines.withContext
31+
import okhttp3.internal.wait
3032
import timber.log.Timber
33+
import java.io.IOException
3134
import java.lang.reflect.InvocationHandler
3235
import java.lang.reflect.Method
3336
import java.lang.reflect.Proxy
@@ -75,8 +78,8 @@ class NearbyParentFragmentPresenter
7578
* - **connnectionCount**: number of parallel requests
7679
*/
7780
private object LoadPlacesAsyncOptions {
78-
const val BATCH_SIZE = 3
79-
const val CONNECTION_COUNT = 3
81+
const val BATCH_SIZE = 10
82+
const val CONNECTION_COUNT = 20
8083
}
8184

8285
private var schedulePlacesUpdateJob: Job? = null
@@ -91,7 +94,7 @@ class NearbyParentFragmentPresenter
9194
private object SchedulePlacesUpdateOptions {
9295
var skippedCount = 0
9396
const val SKIP_LIMIT = 3
94-
const val SKIP_DELAY_MS = 500L
97+
const val SKIP_DELAY_MS = 100L
9598
}
9699

97100
// used to tell the asynchronous place detail loading job that the places' bookmarked status
@@ -379,13 +382,32 @@ class NearbyParentFragmentPresenter
379382
)
380383
} catch (e: Exception) {
381384
Timber.tag("NearbyPinDetails").e(e)
382-
collectResults.send(indices.map { Pair(it, updatedGroups[it]) })
385+
//HTTP request failed. Try individual places
386+
for (i in indices) {
387+
launch {
388+
val onePlaceBatch = mutableListOf<Pair<Int, MarkerPlaceGroup>>()
389+
try {
390+
val fetchedPlace = nearbyController.getPlaces(
391+
mutableListOf(updatedGroups[i].place)
392+
)
393+
394+
onePlaceBatch.add(Pair(i, MarkerPlaceGroup(
395+
bookmarkLocationDao.findBookmarkLocation(
396+
fetchedPlace[0]),fetchedPlace[0])))
397+
} catch (e: Exception) {
398+
Timber.tag("NearbyPinDetails").e(e)
399+
onePlaceBatch.add(Pair(i, updatedGroups[i]))
400+
}
401+
collectResults.send(onePlaceBatch)
402+
}
403+
}
383404
}
384405
}
385406
}
386407
}
387408
var collectCount = 0
388-
for (resultList in collectResults) {
409+
while (collectCount < indicesToUpdate.size) {
410+
val resultList = collectResults.receive()
389411
for ((index, fetchedPlaceGroup) in resultList) {
390412
val existingPlace = updatedGroups[index].place
391413
val finalPlaceGroup = MarkerPlaceGroup(
@@ -442,9 +464,7 @@ class NearbyParentFragmentPresenter
442464
}
443465
}
444466
schedulePlacesUpdate(updatedGroups)
445-
if (++collectCount == totalBatches) {
446-
break
447-
}
467+
collectCount += resultList.size
448468
}
449469
collectResults.close()
450470
}

0 commit comments

Comments
 (0)