Skip to content

Commit a79dd87

Browse files
authored
Add metadata to SDK ready (#849)
1 parent 19879da commit a79dd87

26 files changed

Lines changed: 579 additions & 200 deletions

File tree

api/src/main/java/io/split/android/client/SplitClient.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,23 +183,29 @@ public interface SplitClient extends AttributesManager {
183183
/**
184184
* Registers an event listener for SDK events that provide typed metadata.
185185
* <p>
186-
* This method provides type-safe callbacks for SDK_UPDATE and SDK_READY_FROM_CACHE events.
186+
* This method provides type-safe callbacks for SDK_READY, SDK_UPDATE, and SDK_READY_FROM_CACHE events.
187187
* Override the methods you need in the listener.
188188
* <p>
189189
* Example usage:
190190
* <pre>{@code
191191
* client.addEventListener(new SdkEventListener() {
192192
* @Override
193+
* public void onReady(SplitClient client, SdkReadyMetadata metadata) {
194+
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
195+
* // Handle SDK ready on background thread
196+
* }
197+
*
198+
* @Override
193199
* public void onUpdate(SplitClient client, SdkUpdateMetadata metadata) {
194200
* SdkUpdateMetadata.Type type = metadata.getType(); // FLAGS_UPDATE or SEGMENTS_UPDATE
195201
* List<String> names = metadata.getNames(); // updated flag/segment names
196202
* // Handle on background thread
197203
* }
198204
*
199205
* @Override
200-
* public void onReadyFromCacheView(SplitClient client, SdkReadyFromCacheMetadata metadata) {
206+
* public void onReadyFromCacheView(SplitClient client, SdkReadyMetadata metadata) {
201207
* // Handle on main/UI thread
202-
* Boolean freshInstall = metadata.isFreshInstall();
208+
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
203209
* }
204210
* });
205211
* }</pre>

api/src/main/java/io/split/android/client/events/SdkEventListener.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,53 @@
1616
* <pre>{@code
1717
* client.addEventListener(new SdkEventListener() {
1818
* @Override
19+
* public void onReady(SplitClient client, SdkReadyMetadata metadata) {
20+
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
21+
* // Handle ready on background thread
22+
* }
23+
*
24+
* @Override
1925
* public void onUpdate(SplitClient client, SdkUpdateMetadata metadata) {
2026
* SdkUpdateMetadata.Type type = metadata.getType(); // FLAGS_UPDATE or SEGMENTS_UPDATE
2127
* List<String> names = metadata.getNames(); // updated flag/segment names
2228
* // Handle updates on background thread
2329
* }
2430
*
2531
* @Override
26-
* public void onReadyFromCacheView(SplitClient client, SdkReadyFromCacheMetadata metadata) {
32+
* public void onReadyFromCacheView(SplitClient client, SdkReadyMetadata metadata) {
2733
* // Handle cache ready on main/UI thread
28-
* Boolean freshInstall = metadata.isFreshInstall();
34+
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
2935
* }
3036
* });
3137
* }</pre>
3238
*/
3339
public abstract class SdkEventListener {
3440

41+
/**
42+
* Called when SDK_READY event occurs, executed on a background thread.
43+
* <p>
44+
* Override this method to handle SDK_READY events with typed metadata.
45+
*
46+
* @param client the Split client instance
47+
* @param metadata the typed metadata containing ready state information
48+
*/
49+
public void onReady(SplitClient client, SdkReadyMetadata metadata) {
50+
// Default empty implementation
51+
}
52+
53+
/**
54+
* Called when SDK_READY event occurs, executed on the main/UI thread.
55+
* <p>
56+
* Override this method to handle SDK_READY events with typed metadata on the main thread.
57+
* Use this when you need to update UI components.
58+
*
59+
* @param client the Split client instance
60+
* @param metadata the typed metadata containing ready state information
61+
*/
62+
public void onReadyView(SplitClient client, SdkReadyMetadata metadata) {
63+
// Default empty implementation
64+
}
65+
3566
/**
3667
* Called when SDK_UPDATE event occurs, executed on a background thread.
3768
* <p>
@@ -52,7 +83,7 @@ public void onUpdate(SplitClient client, SdkUpdateMetadata metadata) {
5283
* @param client the Split client instance
5384
* @param metadata the typed metadata containing cache information
5485
*/
55-
public void onReadyFromCache(SplitClient client, SdkReadyFromCacheMetadata metadata) {
86+
public void onReadyFromCache(SplitClient client, SdkReadyMetadata metadata) {
5687
// Default empty implementation
5788
}
5889

@@ -78,8 +109,7 @@ public void onUpdateView(SplitClient client, SdkUpdateMetadata metadata) {
78109
* @param client the Split client instance
79110
* @param metadata the typed metadata containing cache information
80111
*/
81-
public void onReadyFromCacheView(SplitClient client, SdkReadyFromCacheMetadata metadata) {
112+
public void onReadyFromCacheView(SplitClient client, SdkReadyMetadata metadata) {
82113
// Default empty implementation
83114
}
84115
}
85-

api/src/main/java/io/split/android/client/events/SdkReadyFromCacheMetadata.java

Lines changed: 0 additions & 49 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package io.split.android.client.events;
2+
3+
import androidx.annotation.Nullable;
4+
5+
/**
6+
* Typed metadata for SDK_READY and SDK_READY_FROM_CACHE events.
7+
* <p>
8+
* Contains information about the cache state when the SDK becomes ready.
9+
*/
10+
public final class SdkReadyMetadata {
11+
12+
@Nullable
13+
private final Boolean mInitialCacheLoad;
14+
15+
@Nullable
16+
private final Long mLastUpdateTimestamp;
17+
18+
/**
19+
* Creates a new SdkReadyMetadata instance.
20+
*
21+
* @param initialCacheLoad true if this is an initial cache load with no usable cache, or null if not available
22+
* @param lastUpdateTimestamp the last successful cache timestamp in milliseconds since epoch, or null if not available
23+
*/
24+
public SdkReadyMetadata(@Nullable Boolean initialCacheLoad, @Nullable Long lastUpdateTimestamp) {
25+
mInitialCacheLoad = initialCacheLoad;
26+
mLastUpdateTimestamp = lastUpdateTimestamp;
27+
}
28+
29+
/**
30+
* Returns whether this is an initial cache load with no usable cache.
31+
* <p>
32+
* This is true when the SDK starts without any prior cached data (fresh install),
33+
* meaning data was fetched from the server for the first time.
34+
*
35+
* @return true if initial cache load, false otherwise, or null if not available
36+
*/
37+
@Nullable
38+
public Boolean isInitialCacheLoad() {
39+
return mInitialCacheLoad;
40+
}
41+
42+
/**
43+
* Returns the last successful cache timestamp in milliseconds since epoch.
44+
*
45+
* @return the timestamp, or null if not available
46+
*/
47+
@Nullable
48+
public Long getLastUpdateTimestamp() {
49+
return mLastUpdateTimestamp;
50+
}
51+
}
52+

api/src/test/java/io/split/android/client/events/SdkReadyFromCacheMetadataTest.java

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package io.split.android.client.events;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertNull;
6+
import static org.junit.Assert.assertTrue;
7+
8+
import org.junit.Test;
9+
10+
public class SdkReadyMetadataTest {
11+
12+
@Test
13+
public void isInitialCacheLoadReturnsNullWhenConstructedWithNull() {
14+
SdkReadyMetadata metadata = new SdkReadyMetadata(null, null);
15+
16+
assertNull(metadata.isInitialCacheLoad());
17+
}
18+
19+
@Test
20+
public void isInitialCacheLoadReturnsTrueWhenConstructedWithTrue() {
21+
SdkReadyMetadata metadata = new SdkReadyMetadata(true, null);
22+
23+
assertTrue(metadata.isInitialCacheLoad());
24+
}
25+
26+
@Test
27+
public void isInitialCacheLoadReturnsFalseWhenConstructedWithFalse() {
28+
SdkReadyMetadata metadata = new SdkReadyMetadata(false, null);
29+
30+
assertFalse(metadata.isInitialCacheLoad());
31+
}
32+
33+
@Test
34+
public void getLastUpdateTimestampReturnsNullWhenConstructedWithNull() {
35+
SdkReadyMetadata metadata = new SdkReadyMetadata(null, null);
36+
37+
assertNull(metadata.getLastUpdateTimestamp());
38+
}
39+
40+
@Test
41+
public void getLastUpdateTimestampReturnsValueWhenConstructedWithValue() {
42+
long timestamp = 1704067200000L;
43+
SdkReadyMetadata metadata = new SdkReadyMetadata(null, timestamp);
44+
45+
assertEquals(Long.valueOf(timestamp), metadata.getLastUpdateTimestamp());
46+
}
47+
48+
@Test
49+
public void bothValuesReturnCorrectlyWhenBothAreSet() {
50+
long timestamp = 1704067200000L;
51+
SdkReadyMetadata metadata = new SdkReadyMetadata(true, timestamp);
52+
53+
assertTrue(metadata.isInitialCacheLoad());
54+
assertEquals(Long.valueOf(timestamp), metadata.getLastUpdateTimestamp());
55+
}
56+
57+
@Test
58+
public void bothValuesReturnCorrectlyWhenInitialCacheLoadIsFalse() {
59+
long timestamp = 1704067200000L;
60+
SdkReadyMetadata metadata = new SdkReadyMetadata(false, timestamp);
61+
62+
assertFalse(metadata.isInitialCacheLoad());
63+
assertEquals(Long.valueOf(timestamp), metadata.getLastUpdateTimestamp());
64+
}
65+
}
66+

events-domain/src/main/java/io/split/android/client/events/EventsManagerCoordinator.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,20 @@ private void propagateTriggeredEvents(ISplitEventsManager splitEventsManager) {
127127
}
128128
}
129129
}
130+
131+
/**
132+
* Checks if an external event has already been triggered in any registered manager.
133+
*
134+
* @param event the event to check
135+
* @return true if the event has already been triggered in any manager, false otherwise
136+
*/
137+
@Override
138+
public boolean eventAlreadyTriggered(SplitEvent event) {
139+
for (ISplitEventsManager manager : mManagers.values()) {
140+
if (manager.eventAlreadyTriggered(event)) {
141+
return true;
142+
}
143+
}
144+
return false;
145+
}
130146
}

events-domain/src/main/java/io/split/android/client/events/ISplitEventsManager.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,12 @@ public interface ISplitEventsManager {
1515
* @param metadata the event metadata, can be null
1616
*/
1717
void notifyInternalEvent(SplitInternalEvent internalEvent, @Nullable EventMetadata metadata);
18+
19+
/**
20+
* Checks if an external event has already been triggered.
21+
*
22+
* @param event the event to check
23+
* @return true if the event has already been triggered (reached its max executions), false otherwise
24+
*/
25+
boolean eventAlreadyTriggered(SplitEvent event);
1826
}

0 commit comments

Comments
 (0)