|
47 | 47 | import java.util.Date;
|
48 | 48 | import java.util.HashSet;
|
49 | 49 | import java.util.List;
|
50 |
| -import java.util.Map; |
51 | 50 | import java.util.Set;
|
52 | 51 | import java.util.UUID;
|
53 | 52 | import java.util.concurrent.TimeUnit;
|
54 | 53 |
|
55 | 54 | /**
|
56 | 55 | * An online index that can also be mirrored locally.
|
57 | 56 | *
|
58 |
| - * You cannot construct this class directly. Please use {@link OfflineClient#getIndex(String)} to obtain an instance. |
59 |
| -
|
60 |
| - * <p>When created, an instance of this class has its <code>mirrored</code> flag set to false, and behaves like a normal, |
61 |
| - * online {@link Index}. When the <code>mirrored</code> flag is set to true, the index becomes capable of acting upon |
62 |
| - * local data.</p> |
| 57 | + * **Note:** You cannot construct this class directly. Please use {@link OfflineClient#getIndex(String)} to obtain an |
| 58 | + * instance. |
| 59 | + * |
| 60 | + * **Note:** Requires Algolia Offline Core. {@link OfflineClient#enableOfflineMode(String)} must be called with a |
| 61 | + * valid license key prior to calling any offline-related method. |
63 | 62 | *
|
64 |
| - * <p>It is a programming error to call methods acting on the local data when <code>mirrored</code> is false. Doing so |
65 |
| - * will result in an {@link IllegalStateException} being thrown.</p> |
| 63 | + * When created, an instance of this class has its `mirrored` flag set to false, and behaves like a normal, |
| 64 | + * online {@link Index}. When the `mirrored` flag is set to true, the index becomes capable of acting upon local data. |
66 | 65 | *
|
67 |
| - * <p>Native resources are lazily instantiated at the first method call requiring them. They are released when the |
68 |
| - * object is garbage-collected. Although the client guards against concurrent accesses, it is strongly discouraged |
69 |
| - * to create more than one <code>MirroredIndex</code> instance pointing to the same index, as that would duplicate |
70 |
| - * native resources.</p> |
| 66 | + * **Warning:** It is a programming error to call methods acting on the local data when `mirrored` is false. Doing so |
| 67 | + * will result in an assertion exception being thrown. |
71 | 68 | *
|
72 |
| - * <p>NOTE: Requires Algolia's SDK. The {@link OfflineClient#enableOfflineMode(String)} method must be called with |
73 |
| - * a valid license key prior to calling any offline-related method.</p> |
74 | 69 | *
|
75 |
| - * <h3>Request strategy</h3> |
| 70 | + * ## Request strategy |
76 | 71 | *
|
77 | 72 | * When the index is mirrored and the device is online, it becomes possible to transparently switch between online and
|
78 | 73 | * offline requests. There is no single best strategy for that, because it depends on the use case and the current
|
79 |
| - * network conditions. You can choose the strategy through {@link #setRequestStrategy(Strategy)}. The default is |
80 |
| - * {@link Strategy#FALLBACK_ON_FAILURE}, which will always target the online API first, then fallback to the offline |
81 |
| - * mirror in case of failure (including network unavailability). |
| 74 | + * network conditions. You can choose the strategy via {@link #setRequestStrategy(Strategy) setRequestStrategy}. The |
| 75 | + * default is {@link Strategy#FALLBACK_ON_FAILURE FALLBACK_ON_FAILURE}, which will always target the online API first, |
| 76 | + * then fallback to the offline mirror in case of failure (including network unavailability). |
82 | 77 | *
|
83 |
| - * NOTE: If you want to explicitly target either the online API or the offline mirror, doing so is always possible |
84 |
| - * using the {@link #searchOnlineAsync(Query, CompletionHandler)} or {@link #searchOfflineAsync(Query, CompletionHandler)} |
85 |
| - * methods. |
| 78 | + * **Note:** If you want to explicitly target either the online API or the offline mirror, doing so is always possible |
| 79 | + * using the {@link #searchOnlineAsync searchOnlineAsync} or {@link #searchOfflineAsync searchOfflineAsync} methods. |
86 | 80 | *
|
87 |
| - * NOTE: The strategy applies both to {@link #searchAsync(Query, CompletionHandler)} and |
88 |
| - * {@link #searchDisjunctiveFacetingAsync(Query, List, Map, CompletionHandler)}. |
| 81 | + * **Note:** The strategy applies to: |
| 82 | + * |
| 83 | + * - `searchAsync` |
| 84 | + * - `searchDisjunctiveFacetingAsync` |
| 85 | + * - `multipleQueriesAsync` |
| 86 | + * - `getObjectAsync` |
| 87 | + * - `getObjectsAsync` |
89 | 88 | *
|
90 | 89 | *
|
91 | 90 | * ## Bootstrapping
|
92 | 91 | *
|
93 | 92 | * Before the first sync has successfully completed, a mirrored index is not available offline, because it has simply
|
94 |
| - * no data to search in yet. In most cases, this is not a problem: the app will sync as soon as possible, so unless |
| 93 | + * no data to search in yet. In most cases, this is not a problem: the app will sync as soon as instructed, so unless |
95 | 94 | * the device is offline when the app is started for the first time, or unless search is required right after the
|
96 | 95 | * first launch, the user should not notice anything.
|
97 | 96 | *
|
98 | 97 | * However, in some cases, you might need to have offline data available as soon as possible. To achieve that,
|
99 |
| - * `MirroredIndex` provides a **bootstrapping** feature. |
| 98 | + * `MirroredIndex` provides a **manual build** feature. |
| 99 | + * |
| 100 | + * ### Manual build |
100 | 101 | *
|
101 |
| - * Bootstrapping consists in prepackaging with your app the data necessary to build your index, in JSON format; |
102 |
| - * namely: |
| 102 | + * Manual building consists in specifying the source data for your index from local files, instead of downloading it |
| 103 | + * from the API. Namely, you need: |
103 | 104 | *
|
104 |
| - * - settings (one file) |
105 |
| - * - objects (as many files as needed, each containing an array of objects) |
| 105 | + * - the **index settings** (one JSON file); and |
| 106 | + * - the **objects** (as many JSON files as needed, each containing an array of objects). |
106 | 107 | *
|
107 |
| - * Then, upon application startup, call one of the `bootstrap*` methods. This will check if data already exists for the |
108 |
| - * mirror and, if not, populate the mirror with the provided data. It also guarantees that a sync will not be started |
109 |
| - * in the meantime, thus avoiding race conditions. |
| 108 | + * Those files are typically embedded in the application as resources, although any other origin works too. |
110 | 109 | *
|
111 |
| - * ### Discussion |
| 110 | + * ### Conditional bootstrapping |
| 111 | + * |
| 112 | + * To avoid replacing the local mirror every time the app is started (and potentially overwriting more recent data |
| 113 | + * synced from the API), you should test whether the index already has offline data using {@link #hasOfflineData()}. |
| 114 | + * |
| 115 | + * #### Discussion |
112 | 116 | *
|
113 | 117 | * **Warning:** We strongly advise against prepackaging index files. While it may work in some cases, Algolia Offline
|
114 | 118 | * makes no guarantee whatsoever that the index file format will remain backward-compatible forever, nor that it
|
115 | 119 | * is independent of the hardware architecture (e.g. 32 bits vs 64 bits, or Little Endian vs Big Endian). Instead,
|
116 |
| - * always use the official bootstrapping feature. |
| 120 | + * always use the manual build feature. |
117 | 121 | *
|
118 |
| - * While bootstrapping involves building the offline index on the device, and therefore incurs a small delay before |
119 |
| - * the mirror is actually usable, using plain JSON offers a few advantages compared to prepackaging the index file |
| 122 | + * While a manual build involves computing the offline index on the device, and therefore incurs a small delay before |
| 123 | + * the mirror is actually usable, using plain JSON offers several advantages compared to prepackaging the index file |
120 | 124 | * itself:
|
121 | 125 | *
|
122 | 126 | * - You only need to ship the raw object data, which is smaller than shipping an entire index file, which contains
|
123 | 127 | * both the raw data *and* indexing metadata.
|
124 | 128 | *
|
125 |
| - * - Plain JSON compresses well with standard compression techniques like GZip, whereas an index file has a binary |
| 129 | + * - Plain JSON compresses well with standard compression techniques like GZip, whereas an index file uses a binary |
126 | 130 | * format which doesn't compress very efficiently.
|
127 | 131 | *
|
128 | 132 | * - Build automation is facilitated: you can easily extract the required data from your back-end, whereas building
|
129 | 133 | * an index would involve running the app on each mobile platform as part of your build process and capturing the
|
130 | 134 | * filesystem.
|
131 | 135 | *
|
132 | 136 | * Also, the build process is purposedly single-threaded across all indices, which means that on most modern devices
|
133 |
| - * with multi-core CPUs, the impact of bootstrapping on the app's performance will be very moderate, especially |
| 137 | + * with multi-core CPUs, the impact of manual building on the app's performance will be very moderate, especially |
134 | 138 | * regarding UI responsiveness.
|
135 | 139 | *
|
136 | 140 | *
|
|
150 | 154 | *
|
151 | 155 | * - Dictionary-based **plurals** are not supported. ("Simple" plurals with a final S are supported.)
|
152 | 156 | *
|
153 |
| - * - **IP geolocation** (see {@link Query#setAroundLatLngViaIP}) is not supported. |
| 157 | + * - **IP geolocation** (see {@link Query#setAroundLatLngViaIP(Boolean)}) is not supported. |
154 | 158 | *
|
155 | 159 | * - **CJK segmentation** is not supported.
|
156 | 160 | */
|
@@ -648,7 +652,7 @@ public Request buildOfflineFromFiles(@NonNull final File settingsFile, @NonNull
|
648 | 652 | }
|
649 | 653 |
|
650 | 654 | /**
|
651 |
| - * Replace the local mirror with local data stored on the filesystem. |
| 655 | + * Replace the local mirror with local data stored in raw resources. |
652 | 656 | *
|
653 | 657 | * @param resources A {@link Resources} instance to read resources from.
|
654 | 658 | * @param settingsResId Resource identifier of the index settings, in JSON format.
|
|
0 commit comments