Dbrant has uploaded a new change for review. https://gerrit.wikimedia.org/r/196974
Change subject: Cache pages on disk instead of ram. ...................................................................... Cache pages on disk instead of ram. Change-Id: I08cf2aa15895456013145ee5991ee52b0d780d3d --- A wikipedia/assets/licenses/DiskLruCache M wikipedia/build.gradle M wikipedia/res/values/credits.xml M wikipedia/src/main/java/org/wikipedia/Utils.java M wikipedia/src/main/java/org/wikipedia/WikipediaApp.java M wikipedia/src/main/java/org/wikipedia/editing/EditHandler.java M wikipedia/src/main/java/org/wikipedia/page/Page.java M wikipedia/src/main/java/org/wikipedia/page/PageCache.java M wikipedia/src/main/java/org/wikipedia/page/PageProperties.java M wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java M wikipedia/src/main/java/org/wikipedia/page/Section.java M wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryActivity.java M wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryCollection.java M wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryItem.java 14 files changed, 328 insertions(+), 124 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia refs/changes/74/196974/1 diff --git a/wikipedia/assets/licenses/DiskLruCache b/wikipedia/assets/licenses/DiskLruCache new file mode 100644 index 0000000..183fd1f --- /dev/null +++ b/wikipedia/assets/licenses/DiskLruCache @@ -0,0 +1,14 @@ +Copyright 2012 Jake Wharton +Copyright 2011 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/wikipedia/build.gradle b/wikipedia/build.gradle index 858599c..13face6 100644 --- a/wikipedia/build.gradle +++ b/wikipedia/build.gradle @@ -109,6 +109,7 @@ } compile 'de.keyboardsurfer.android.widget:crouton:1.8.5@aar' compile 'com.github.chrisbanes.photoview:library:1.2.3' + compile 'com.jakewharton:disklrucache:2.0.2' } // The next block is for setting the release signing config from a file outside the git repo diff --git a/wikipedia/res/values/credits.xml b/wikipedia/res/values/credits.xml index 15b75a5..2e6f0cd 100644 --- a/wikipedia/res/values/credits.xml +++ b/wikipedia/res/values/credits.xml @@ -9,6 +9,10 @@ <!-- https://raw.githubusercontent.com/keyboardsurfer/Crouton/master/LICENSE --> (<a href="file:///android_asset/licenses/Crouton">license</a>), + <a href="https://github.com/JakeWharton/DiskLruCache">DiskLruCache</a> + <!-- https://github.com/JakeWharton/DiskLruCache/blob/master/LICENSE.txt --> + (<a href="file:///android_asset/licenses/DiskLruCache">license</a>), + <a href="https://github.com/kevinsawicki/http-request">Http-Request</a> <!-- https://raw.githubusercontent.com/kevinsawicki/http-request/master/LICENSE.md --> (<a href="file:///android_asset/licenses/Http-Request">license</a>), diff --git a/wikipedia/src/main/java/org/wikipedia/Utils.java b/wikipedia/src/main/java/org/wikipedia/Utils.java index 6c188d0..b7ab610 100644 --- a/wikipedia/src/main/java/org/wikipedia/Utils.java +++ b/wikipedia/src/main/java/org/wikipedia/Utils.java @@ -498,11 +498,14 @@ * @throws IOException when writing failed */ public static void writeToFile(File file, JSONObject jsonObject) throws IOException { - OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file)); - try { + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file))) { writer.write(jsonObject.toString()); - } finally { - writer.close(); + } + } + + public static void writeToStream(OutputStream outputStream, String contents) throws IOException { + try (OutputStreamWriter writer = new OutputStreamWriter(outputStream)) { + writer.write(contents); } } @@ -513,16 +516,13 @@ * @throws JSONException */ public static JSONObject readJSONFile(File f) throws IOException, JSONException { - BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f))); - try { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)))) { StringBuilder stringBuilder = new StringBuilder(); String readStr; while ((readStr = reader.readLine()) != null) { stringBuilder.append(readStr); } return new JSONObject(stringBuilder.toString()); - } finally { - reader.close(); } } @@ -532,16 +532,13 @@ * @throws IOException */ public static String readFile(final InputStream inputStream) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - try { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { StringBuilder stringBuilder = new StringBuilder(); String readStr; while ((readStr = reader.readLine()) != null) { stringBuilder.append(readStr).append('\n'); } return stringBuilder.toString(); - } finally { - reader.close(); } } diff --git a/wikipedia/src/main/java/org/wikipedia/WikipediaApp.java b/wikipedia/src/main/java/org/wikipedia/WikipediaApp.java index 0fa564e..23435eb 100644 --- a/wikipedia/src/main/java/org/wikipedia/WikipediaApp.java +++ b/wikipedia/src/main/java/org/wikipedia/WikipediaApp.java @@ -186,7 +186,7 @@ Api.setConnectionFactory(new OkHttpConnectionFactory(this)); zeroHandler = new WikipediaZeroHandler(this); - pageCache = new PageCache(); + pageCache = new PageCache(this); new PerformMigrationsTask().execute(); } diff --git a/wikipedia/src/main/java/org/wikipedia/editing/EditHandler.java b/wikipedia/src/main/java/org/wikipedia/editing/EditHandler.java index d483c8d..f270cda 100644 --- a/wikipedia/src/main/java/org/wikipedia/editing/EditHandler.java +++ b/wikipedia/src/main/java/org/wikipedia/editing/EditHandler.java @@ -86,7 +86,7 @@ return; } int id = messagePayload.optInt("sectionID"); - Section section = Section.findSectionForID(currentPage.getSections(), id); + Section section = currentPage.getSections().get(id); Intent intent = new Intent(fragment.getActivity(), EditSectionActivity.class); intent.setAction(EditSectionActivity.ACTION_EDIT_SECTION); intent.putExtra(EditSectionActivity.EXTRA_SECTION_ID, section.getId()); diff --git a/wikipedia/src/main/java/org/wikipedia/page/Page.java b/wikipedia/src/main/java/org/wikipedia/page/Page.java index 483aead..d7382e2 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/Page.java +++ b/wikipedia/src/main/java/org/wikipedia/page/Page.java @@ -107,6 +107,9 @@ } json.putOpt("sections", sectionsJSON); json.putOpt("properties", pageProperties.toJSON()); + if (galleryCollection != null) { + json.put("gallery", galleryCollection.toJSON()); + } return json; } catch (JSONException e) { // This will never happen. Java stinks. @@ -122,5 +125,8 @@ sections.add(new Section(sectionsJSON.optJSONObject(i))); } pageProperties = new PageProperties(json.optJSONObject("properties")); + if (json.has("gallery")) { + galleryCollection = new GalleryCollection(json.optJSONObject("gallery")); + } } } diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageCache.java b/wikipedia/src/main/java/org/wikipedia/page/PageCache.java index ff5fb2c..75b19de 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageCache.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageCache.java @@ -1,38 +1,182 @@ package org.wikipedia.page; import org.wikipedia.PageTitle; +import org.wikipedia.Utils; +import org.wikipedia.concurrency.SaneAsyncTask; -import java.util.*; +import com.jakewharton.disklrucache.DiskLruCache; +import org.json.JSONObject; +import android.content.Context; +import android.os.Environment; +import android.util.Log; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; /** - * Implements a cache of Page objects, to be readily retrieved from memory. - * TODO: make this Parcelable? (or save/restore it from physical storage?) + * Implements a cache of Page objects. */ public class PageCache { + private static final String TAG = "PageCache"; + private static final int DISK_CACHE_VERSION = 1; + private static final int DISK_CACHE_SIZE = 1024 * 1024 * 64; // 64MB + private static final String DISK_CACHE_SUBDIR = "wp_pagecache"; - private static final int MAX_CACHE_ITEMS = 10; - private static final float CACHE_LOAD_FACTOR = 0.75f; + private DiskLruCache mDiskLruCache; + private final Object mDiskCacheLock = new Object(); - private LinkedHashMap<PageTitle, Page> items; + public PageCache(Context context) { + // Initialize disk cache on background thread + File cacheDir = getDiskCacheDir(context, DISK_CACHE_SUBDIR); + new InitDiskCacheTask(cacheDir).execute(); + } - public PageCache() { - items = new LinkedHashMap<PageTitle, Page>(MAX_CACHE_ITEMS, CACHE_LOAD_FACTOR, true) { - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > MAX_CACHE_ITEMS; + private class InitDiskCacheTask extends SaneAsyncTask<Void> { + private final File cacheDir; + + public InitDiskCacheTask(File cacheDir) { + super(SINGLE_THREAD); + this.cacheDir = cacheDir; + } + + @Override + public Void performTask() throws Throwable { + synchronized (mDiskCacheLock) { + mDiskLruCache = DiskLruCache.open(cacheDir, DISK_CACHE_VERSION, 1, DISK_CACHE_SIZE); + mDiskCacheLock.notifyAll(); // Wake any waiting threads } - }; + return null; + } + + @Override + public void onCatch(Throwable caught) { + Log.e(TAG, "Caught " + caught.getMessage(), caught); + caught.printStackTrace(); + } } - public boolean has(PageTitle title) { - return items.containsKey(title); + public interface CachePutListener { + void onPutComplete(); + void onPutError(Throwable e); } - public Page get(PageTitle title) { - return items.get(title); + public void put(PageTitle title, Page page, final CachePutListener listener) { + new AddPageToCacheTask(title, page) { + @Override + public void onFinish(Void v) { + listener.onPutComplete(); + } + + @Override + public void onCatch(Throwable caught) { + listener.onPutError(caught); + } + }.execute(); } - public void put(PageTitle title, Page page) { - items.put(title, page); + private class AddPageToCacheTask extends SaneAsyncTask<Void> { + private final PageTitle title; + private final Page page; + + public AddPageToCacheTask(PageTitle title, Page page) { + super(SINGLE_THREAD); + this.title = title; + this.page = page; + } + + @Override + public Void performTask() throws Throwable { + synchronized (mDiskCacheLock) { + if (mDiskLruCache == null) { + return null; + } + DiskLruCache.Editor editor = null; + try { + Log.d(TAG, "Writing to cache: " + title.getDisplayText()); + String key = title.getIdentifier(); + editor = mDiskLruCache.edit(key); + if (editor == null) { + return null; + } + OutputStream outputStream = new BufferedOutputStream(editor.newOutputStream(0)); + Utils.writeToStream(outputStream, page.toJSON().toString()); + mDiskLruCache.flush(); + editor.commit(); + } catch (IOException e) { + if (editor != null) { + editor.abort(); + } + } + } + return null; + } + } + + public interface CacheGetListener { + void onGetComplete(Page page); + void onGetError(Throwable e); + } + + public void get(PageTitle title, final CacheGetListener listener) { + new GetPageFromCacheTask(title) { + @Override + public void onFinish(Page page) { + listener.onGetComplete(page); + } + + @Override + public void onCatch(Throwable caught) { + listener.onGetError(caught); + } + }.execute(); + } + + private class GetPageFromCacheTask extends SaneAsyncTask<Page> { + private final PageTitle title; + + public GetPageFromCacheTask(PageTitle title) { + super(SINGLE_THREAD); + this.title = title; + } + + @Override + public Page performTask() throws Throwable { + synchronized (mDiskCacheLock) { + if (mDiskLruCache == null) { + return null; + } + String key = title.getIdentifier(); + DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); + if (snapshot == null) { + return null; + } + try { + Log.d(TAG, "Reading from cache: " + title.getDisplayText()); + InputStream inputStream = new BufferedInputStream(snapshot.getInputStream(0)); + String jsonStr = Utils.readFile(inputStream); + return new Page(new JSONObject(jsonStr)); + } finally { + snapshot.close(); + } + } + } + } + + // Creates a unique subdirectory of the designated app cache directory. Tries to use external + // storage, but if not mounted, falls back on internal storage. + public static File getDiskCacheDir(Context context, String uniqueName) { + // Check if media is mounted or storage is built-in, if so, try and use external cache dir + // otherwise use internal cache dir. + final String cachePath; + if ((Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || + Environment.isExternalStorageRemovable()) && context.getExternalCacheDir() != null) { + cachePath = context.getExternalCacheDir().getPath(); + } else { + cachePath = context.getCacheDir().getPath(); + } + return new File(cachePath + File.separator + uniqueName); } } diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java b/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java index 09003b7..2360b4c 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageProperties.java @@ -213,7 +213,7 @@ } if (leadImageName != null) { JSONObject imageObject = new JSONObject(); - imageObject.put("file", leadImageUrl); + imageObject.put("file", leadImageName); json.put("image", imageObject); } } catch (JSONException e) { diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java index ed2ef10..e57c225 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java @@ -105,6 +105,8 @@ */ private boolean saveOnComplete = false; + private boolean cacheOnComplete = true; + private PageViewFragment parentFragment; private PageTitle title; @@ -424,12 +426,35 @@ } //is this page in cache?? - if (app.getPageCache().has(titleOriginal)) { - Log.d(TAG, "Using page from cache: " + titleOriginal.getDisplayText()); - page = app.getPageCache().get(titleOriginal); - title = page.getTitle(); - state = STATE_COMPLETE_FETCH; - } + getActivity().updateProgressBar(true, true, 0); + app.getPageCache().get(titleOriginal, new PageCache.CacheGetListener() { + @Override + public void onGetComplete(Page page) { + if (page != null) { + Log.d(TAG, "Using page from cache: " + titleOriginal.getDisplayText()); + PageViewFragmentInternal.this.page = page; + title = page.getTitle(); + state = STATE_COMPLETE_FETCH; + cacheOnComplete = false; + } else { + // fetch the page from the network... + state = STATE_NO_FETCH; + cacheOnComplete = true; + } + setState(state); + performActionForState(state); + } + + @Override + public void onGetError(Throwable e) { + Log.e(TAG, "Failed to get page from cache: " + e); + e.printStackTrace(); + state = STATE_NO_FETCH; + cacheOnComplete = true; + setState(state); + performActionForState(state); + } + }); if (tocHandler == null) { tocHandler = new ToCHandler(getActivity(), @@ -438,9 +463,6 @@ title.getSite(), isFirstPage()); } - - setState(state); - performActionForState(state); } private boolean isFirstPage() { @@ -630,10 +652,23 @@ tocHandler.setupToC(page); //add the page to cache! - app.getPageCache().put(titleOriginal, page); - if (!titleOriginal.equals(title)) { - app.getPageCache().put(title, page); + if (cacheOnComplete) { + app.getPageCache().put(titleOriginal, page, new PageCache.CachePutListener() { + @Override + public void onPutComplete() { + } + + @Override + public void onPutError(Throwable e) { + Log.e(TAG, "Failed to add page to cache: " + e); + e.printStackTrace(); + } + }); + //if (!titleOriginal.equals(title)) { + // app.getPageCache().put(title, page); + //} } + } } @@ -780,7 +815,7 @@ Intent galleryIntent = new Intent(); galleryIntent.setClass(getActivity(), GalleryActivity.class); galleryIntent.putExtra(GalleryActivity.EXTRA_IMAGETITLE, imageTitle); - galleryIntent.putExtra(GalleryActivity.EXTRA_PAGETITLE, title); + galleryIntent.putExtra(GalleryActivity.EXTRA_PAGETITLE, titleOriginal); getActivity().startActivityForResult(galleryIntent, PageActivity.ACTIVITY_REQUEST_GALLERY); } @@ -1101,6 +1136,7 @@ public void refreshPage(boolean saveOnComplete) { this.saveOnComplete = saveOnComplete; + cacheOnComplete = true; if (saveOnComplete) { Toast.makeText(getActivity(), R.string.toast_refresh_saved_page, Toast.LENGTH_LONG).show(); } diff --git a/wikipedia/src/main/java/org/wikipedia/page/Section.java b/wikipedia/src/main/java/org/wikipedia/page/Section.java index cfadfab..db06a1a 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/Section.java +++ b/wikipedia/src/main/java/org/wikipedia/page/Section.java @@ -1,17 +1,12 @@ package org.wikipedia.page; -import android.os.Parcel; -import android.os.Parcelable; import org.json.JSONException; import org.json.JSONObject; -import org.wikipedia.Utils; - -import java.util.List; /** * Represents a particular section of an article. */ -public class Section implements Parcelable { +public class Section { private final JSONObject data; @@ -33,35 +28,6 @@ // This, also, will never happen. Very similar to Java being sane, some say. throw new RuntimeException(e); } - } - - // This won't actually throw - private Section(Parcel in) throws JSONException { - this(new JSONObject(in.readString())); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Section)) { - return false; - } - - Section other = (Section) o; - return getId() == other.getId() - && getLevel() == other.getLevel() - && Utils.compareStrings(getHeading(), other.getHeading()) - && Utils.compareStrings(getAnchor(), other.getAnchor()) - && Utils.compareStrings(getContent(), other.getContent()); - - } - - @Override - public int hashCode() { - int result = getId(); - result = 31 * result + getHeading().hashCode(); - result = 31 * result + getAnchor().hashCode(); - result = 31 * result + getContent().hashCode(); - return result; } @Override @@ -99,33 +65,4 @@ return data; } - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeString(toJSON().toString()); - } - - public static final Parcelable.Creator<Section> CREATOR - = new Parcelable.Creator<Section>() { - public Section createFromParcel(Parcel in) { - try { - return new Section(in); - } catch (JSONException e) { - // This won't happen - throw new RuntimeException(e); - } - } - - public Section[] newArray(int size) { - return new Section[size]; - } - }; - - public static Section findSectionForID(List<Section> sections, int id) { - return sections.get(id); - } } diff --git a/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryActivity.java b/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryActivity.java index f4fd8c4..09b7d75 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryActivity.java +++ b/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryActivity.java @@ -12,11 +12,13 @@ import org.wikipedia.page.LinkMovementMethodExt; import org.wikipedia.page.Page; import org.wikipedia.page.PageActivity; +import org.wikipedia.page.PageCache; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentTransaction; @@ -41,6 +43,7 @@ import java.util.Map; public class GalleryActivity extends ThemedActionBarActivity { + private static final String TAG = "GalleryActivity"; public static final int ACTIVITY_RESULT_FILEPAGE_SELECT = 1; public static final String EXTRA_PAGETITLE = "pageTitle"; @@ -49,6 +52,7 @@ private WikipediaApp app; private PageTitle pageTitle; private Page page; + private boolean cacheOnLoad; private GalleryFunnel funnel; public GalleryFunnel getFunnel() { @@ -142,11 +146,6 @@ pageTitle = getIntent().getParcelableExtra(EXTRA_PAGETITLE); initialImageTitle = getIntent().getParcelableExtra(EXTRA_IMAGETITLE); - // find our Page in the page cache... - if (app.getPageCache().has(pageTitle)) { - page = app.getPageCache().get(pageTitle); - } - galleryCache = new HashMap<>(); galleryPager = (ViewPager) findViewById(R.id.gallery_item_pager); galleryAdapter = new GalleryItemAdapter(this); @@ -210,13 +209,30 @@ updateProgressBar(false, true, 0); - // if our page already has a prepopulated gallery collection, then use it! - if (page != null && page.getGalleryCollection() != null) { - applyGalleryCollection(page.getGalleryCollection()); - } else { - // otherwise, fetch it! - fetchGalleryCollection(); - } + // find our Page in the page cache... + app.getPageCache().get(pageTitle, new PageCache.CacheGetListener() { + @Override + public void onGetComplete(Page page) { + GalleryActivity.this.page = page; + if (page != null && page.getGalleryCollection() != null) { + applyGalleryCollection(page.getGalleryCollection()); + cacheOnLoad = false; + } else { + // fetch the gallery from the network... + fetchGalleryCollection(); + cacheOnLoad = true; + } + } + + @Override + public void onGetError(Throwable e) { + Log.e(TAG, "Failed to get page from cache: " + e); + e.printStackTrace(); + fetchGalleryCollection(); + cacheOnLoad = true; + } + }); + } @Override @@ -346,7 +362,7 @@ Intent intent = new Intent(); intent.setClass(GalleryActivity.this, PageActivity.class); intent.setAction(PageActivity.ACTION_PAGE_FOR_TITLE); - intent.putExtra(PageActivity.EXTRA_PAGETITLE, resultTitle); + intent.putExtra(PageActivity.EXTRA_PAGETITLE, (Parcelable) resultTitle); intent.putExtra(PageActivity.EXTRA_HISTORYENTRY, historyEntry); setResult(ACTIVITY_RESULT_FILEPAGE_SELECT, intent); finish(); @@ -365,8 +381,19 @@ public void onGalleryResult(GalleryCollection result) { updateProgressBar(false, true, 0); // save it to our current page, for later use - if (page != null) { + if (cacheOnLoad && page != null) { page.setGalleryCollection(result); + app.getPageCache().put(pageTitle, page, new PageCache.CachePutListener() { + @Override + public void onPutComplete() { + } + + @Override + public void onPutError(Throwable e) { + Log.e(TAG, "Failed to add page to cache: " + e); + e.printStackTrace(); + } + }); } applyGalleryCollection(result); } diff --git a/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryCollection.java b/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryCollection.java index 089c100..b1a8a15 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryCollection.java +++ b/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryCollection.java @@ -1,6 +1,9 @@ package org.wikipedia.page.gallery; import org.wikipedia.PageTitle; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -14,6 +17,36 @@ return itemList; } + public JSONObject toJSON() { + JSONObject json = new JSONObject(); + try { + JSONArray itemsJSON = new JSONArray(); + for (GalleryItem item : itemList) { + JSONObject itemJSON = item.toJSON(); + if (itemJSON != null) { + itemsJSON.put(itemJSON); + } + } + json.put("items", itemsJSON); + return json; + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + public GalleryCollection(JSONObject json) { + itemList = new ArrayList<>(); + try { + JSONArray itemsJSON = json.getJSONArray("items"); + for (int i = 0; i < itemsJSON.length(); i++) { + JSONObject itemJSON = itemsJSON.getJSONObject(i); + itemList.add(new GalleryItem(itemJSON)); + } + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + public GalleryCollection(Map<PageTitle, GalleryItem> galleryMap) { itemList = new ArrayList<>(); Iterator iterator = galleryMap.keySet().iterator(); diff --git a/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryItem.java b/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryItem.java index 03132c0..41f5e09 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryItem.java +++ b/wikipedia/src/main/java/org/wikipedia/page/gallery/GalleryItem.java @@ -9,6 +9,9 @@ import java.util.Map; public class GalleryItem { + private final JSONObject json; + public JSONObject toJSON() { return json; } + private final String name; public String getName() { return name; } @@ -61,6 +64,7 @@ } public GalleryItem(String name) { + this.json = null; this.name = name; this.url = null; this.mimeType = "*/*"; @@ -71,6 +75,7 @@ } public GalleryItem(JSONObject json) throws JSONException { + this.json = json; this.name = json.getString("title"); JSONObject objinfo; if (json.has("imageinfo")) { -- To view, visit https://gerrit.wikimedia.org/r/196974 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I08cf2aa15895456013145ee5991ee52b0d780d3d Gerrit-PatchSet: 1 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: Dbrant <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
