mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 06:43:56 +01:00 
			
		
		
		
	Caching mechanism to reduce API calls
This commit is contained in:
		
							parent
							
								
									4521b5fe99
								
							
						
					
					
						commit
						febed893e8
					
				
					 1 changed files with 80 additions and 28 deletions
				
			
		|  | @ -3,6 +3,7 @@ package fr.free.nrw.commons.review; | |||
| import android.annotation.SuppressLint; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.SharedPreferences; | ||||
| import android.graphics.PorterDuff; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.os.Bundle; | ||||
|  | @ -22,9 +23,12 @@ import fr.free.nrw.commons.media.MediaDetailFragment; | |||
| import fr.free.nrw.commons.theme.BaseActivity; | ||||
| import fr.free.nrw.commons.utils.DialogUtil; | ||||
| import fr.free.nrw.commons.utils.ViewUtil; | ||||
| import io.reactivex.Observable; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.CompositeDisposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import javax.inject.Inject; | ||||
| 
 | ||||
| public class ReviewActivity extends BaseActivity { | ||||
|  | @ -34,6 +38,10 @@ public class ReviewActivity extends BaseActivity { | |||
|     MediaDetailFragment mediaDetailFragment; | ||||
|     public ReviewPagerAdapter reviewPagerAdapter; | ||||
|     public ReviewController reviewController; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     @Inject | ||||
|     ReviewHelper reviewHelper; | ||||
|     @Inject | ||||
|  | @ -52,6 +60,13 @@ public class ReviewActivity extends BaseActivity { | |||
|     final String SAVED_MEDIA = "saved_media"; | ||||
|     private Media media; | ||||
| 
 | ||||
|     private List<Media> cachedMedia = new ArrayList<>(); | ||||
| 
 | ||||
|     private static final String PREF_NAME = "ReviewActivityPrefs"; | ||||
|     private static final String LAST_CACHE_TIME_KEY = "lastCacheTime"; | ||||
|     private static final int CACHE_SIZE = 50; | ||||
|     private static final long CACHE_EXPIRY_TIME = 24 * 60 * 60 * 1000; | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onSaveInstanceState(Bundle outState) { | ||||
|         super.onSaveInstanceState(outState); | ||||
|  | @ -99,10 +114,10 @@ public class ReviewActivity extends BaseActivity { | |||
|         d[2].setColorFilter(getApplicationContext().getResources().getColor(R.color.button_blue), PorterDuff.Mode.SRC_IN); | ||||
| 
 | ||||
|         if (savedInstanceState != null && savedInstanceState.getParcelable(SAVED_MEDIA) != null) { | ||||
|             updateImage(savedInstanceState.getParcelable(SAVED_MEDIA)); // Use existing media if we have one | ||||
|             updateImage(savedInstanceState.getParcelable(SAVED_MEDIA)); | ||||
|             setUpMediaDetailOnOrientation(); | ||||
|         } else { | ||||
|             runRandomizer(); //Run randomizer whenever everything is ready so that a first random image will be added | ||||
|             runRandomizer(); | ||||
|         } | ||||
| 
 | ||||
|         binding.skipImage.setOnClickListener(view -> { | ||||
|  | @ -132,35 +147,69 @@ public class ReviewActivity extends BaseActivity { | |||
| 
 | ||||
|     @SuppressLint("CheckResult") | ||||
|     public boolean runRandomizer() { | ||||
| 
 | ||||
|         hasNonHiddenCategories = false; | ||||
|         binding.pbReviewImage.setVisibility(View.VISIBLE); | ||||
|         binding.viewPagerReview.setCurrentItem(0); | ||||
|         // Finds non-hidden categories from Media instance | ||||
|         compositeDisposable.add(reviewHelper.getRandomMedia() | ||||
| 
 | ||||
|         if (cachedMedia.isEmpty() || isCacheExpired()) { | ||||
|             fetchAndCacheMedia(); | ||||
|         } else { | ||||
|             processNextCachedMedia(); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     private void fetchAndCacheMedia() { | ||||
|         compositeDisposable.add(Observable.range(0, CACHE_SIZE) | ||||
|             .flatMap(i -> reviewHelper.getRandomMedia().toObservable()) | ||||
|             .subscribeOn(Schedulers.io()) | ||||
|             .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe(this::checkWhetherFileIsUsedInWikis)); | ||||
|         return true; | ||||
|             .toList() | ||||
|             .subscribe(mediaList -> { | ||||
|                 cachedMedia.clear(); | ||||
|                 cachedMedia.addAll(mediaList); | ||||
|                 updateLastCacheTime(); | ||||
|                 processNextCachedMedia(); | ||||
|             }, this::handleError)); | ||||
|     } | ||||
| 
 | ||||
|     private void processNextCachedMedia() { | ||||
|         if (!cachedMedia.isEmpty()) { | ||||
|             Media media = cachedMedia.remove(0); | ||||
|             checkWhetherFileIsUsedInWikis(media); | ||||
|         } else { | ||||
|             fetchAndCacheMedia(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private boolean isCacheExpired() { | ||||
|         SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); | ||||
|         long lastCacheTime = prefs.getLong(LAST_CACHE_TIME_KEY, 0); | ||||
|         long currentTime = System.currentTimeMillis(); | ||||
|         return (currentTime - lastCacheTime) > CACHE_EXPIRY_TIME; | ||||
|     } | ||||
| 
 | ||||
|     private void updateLastCacheTime() { | ||||
|         SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); | ||||
|         SharedPreferences.Editor editor = prefs.edit(); | ||||
|         editor.putLong(LAST_CACHE_TIME_KEY, System.currentTimeMillis()); | ||||
|         editor.apply(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether media is used or not in any Wiki Page | ||||
|      */ | ||||
|     @SuppressLint("CheckResult") | ||||
|     private void checkWhetherFileIsUsedInWikis(final Media media) { | ||||
|         compositeDisposable.add(reviewHelper.checkFileUsage(media.getFilename()) | ||||
|             .subscribeOn(Schedulers.io()) | ||||
|             .observeOn(AndroidSchedulers.mainThread()) | ||||
|             .subscribe(result -> { | ||||
|                 // result false indicates media is not used in any wiki | ||||
|                 if (!result) { | ||||
|                     // Finds non-hidden categories from Media instance | ||||
|                     findNonHiddenCategories(media); | ||||
|                 } else { | ||||
|                     runRandomizer(); | ||||
|                     processNextCachedMedia(); | ||||
|                 } | ||||
|             })); | ||||
|             }, this::handleError)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -181,7 +230,6 @@ public class ReviewActivity extends BaseActivity { | |||
|         updateImage(media); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("CheckResult") | ||||
|     private void updateImage(Media media) { | ||||
|         reviewHelper.addViewedImagesToDB(media.getPageId()); | ||||
|         this.media = media; | ||||
|  | @ -191,27 +239,26 @@ public class ReviewActivity extends BaseActivity { | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         //If The Media User and Current Session Username is same then Skip the Image | ||||
|         if (media.getUser() != null && media.getUser().equals(AccountUtil.getUserName(getApplicationContext()))) { | ||||
|             runRandomizer(); | ||||
|             processNextCachedMedia(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         binding.reviewImageView.setImageURI(media.getImageUrl()); | ||||
| 
 | ||||
|         reviewController.onImageRefreshed(media); //file name is updated | ||||
|         reviewController.onImageRefreshed(media); | ||||
|         compositeDisposable.add(reviewHelper.getFirstRevisionOfFile(fileName) | ||||
|             .subscribeOn(Schedulers.io()) | ||||
|             .observeOn(AndroidSchedulers.mainThread()) | ||||
|             .subscribe(revision -> { | ||||
|                 reviewController.firstRevision = revision; | ||||
|                 reviewPagerAdapter.updateFileInformation(); | ||||
|                     @SuppressLint({"StringFormatInvalid", "LocalSuppress"}) String caption = String.format(getString(R.string.review_is_uploaded_by), fileName, revision.getUser()); | ||||
|                 String caption = String.format(getString(R.string.review_is_uploaded_by), fileName, revision.getUser()); | ||||
|                 binding.tvImageCaption.setText(caption); | ||||
|                 binding.pbReviewImage.setVisibility(View.GONE); | ||||
|                 reviewImageFragment = getInstanceOfReviewImageFragment(); | ||||
|                 reviewImageFragment.enableButtons(); | ||||
|                 })); | ||||
|             }, this::handleError)); | ||||
|         binding.viewPagerReview.setCurrentItem(0); | ||||
|     } | ||||
| 
 | ||||
|  | @ -258,6 +305,11 @@ public class ReviewActivity extends BaseActivity { | |||
|                 null, | ||||
|                 null); | ||||
|     } | ||||
|     private void handleError(Throwable error) { | ||||
|         binding.pbReviewImage.setVisibility(View.GONE); | ||||
|         ViewUtil.showShortSnackbar(binding.drawerLayout, R.string.error_review); | ||||
|         // 可以添加更详细的错误处理逻辑 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 24-S2-2-C-Interactive
						24-S2-2-C-Interactive