Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions api/src/main/java/io/split/android/client/SplitClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,23 +183,29 @@ public interface SplitClient extends AttributesManager {
/**
* Registers an event listener for SDK events that provide typed metadata.
* <p>
* This method provides type-safe callbacks for SDK_UPDATE and SDK_READY_FROM_CACHE events.
* This method provides type-safe callbacks for SDK_READY, SDK_UPDATE, and SDK_READY_FROM_CACHE events.
* Override the methods you need in the listener.
* <p>
* Example usage:
* <pre>{@code
* client.addEventListener(new SdkEventListener() {
* @Override
* public void onReady(SplitClient client, SdkReadyMetadata metadata) {
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
* // Handle SDK ready on background thread
* }
*
* @Override
* public void onUpdate(SplitClient client, SdkUpdateMetadata metadata) {
* SdkUpdateMetadata.Type type = metadata.getType(); // FLAGS_UPDATE or SEGMENTS_UPDATE
* List<String> names = metadata.getNames(); // updated flag/segment names
* // Handle on background thread
* }
*
* @Override
* public void onReadyFromCacheView(SplitClient client, SdkReadyFromCacheMetadata metadata) {
* public void onReadyFromCacheView(SplitClient client, SdkReadyMetadata metadata) {
* // Handle on main/UI thread
* Boolean freshInstall = metadata.isFreshInstall();
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
* }
* });
* }</pre>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,53 @@
* <pre>{@code
* client.addEventListener(new SdkEventListener() {
* @Override
* public void onReady(SplitClient client, SdkReadyMetadata metadata) {
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
* // Handle ready on background thread
* }
*
* @Override
* public void onUpdate(SplitClient client, SdkUpdateMetadata metadata) {
* SdkUpdateMetadata.Type type = metadata.getType(); // FLAGS_UPDATE or SEGMENTS_UPDATE
* List<String> names = metadata.getNames(); // updated flag/segment names
* // Handle updates on background thread
* }
*
* @Override
* public void onReadyFromCacheView(SplitClient client, SdkReadyFromCacheMetadata metadata) {
* public void onReadyFromCacheView(SplitClient client, SdkReadyMetadata metadata) {
* // Handle cache ready on main/UI thread
* Boolean freshInstall = metadata.isFreshInstall();
* Boolean initialCacheLoad = metadata.isInitialCacheLoad();
* }
* });
* }</pre>
*/
public abstract class SdkEventListener {

/**
* Called when SDK_READY event occurs, executed on a background thread.
* <p>
* Override this method to handle SDK_READY events with typed metadata.
*
* @param client the Split client instance
* @param metadata the typed metadata containing ready state information
*/
public void onReady(SplitClient client, SdkReadyMetadata metadata) {
// Default empty implementation
}

/**
* Called when SDK_READY event occurs, executed on the main/UI thread.
* <p>
* Override this method to handle SDK_READY events with typed metadata on the main thread.
* Use this when you need to update UI components.
*
* @param client the Split client instance
* @param metadata the typed metadata containing ready state information
*/
public void onReadyView(SplitClient client, SdkReadyMetadata metadata) {
// Default empty implementation
}

/**
* Called when SDK_UPDATE event occurs, executed on a background thread.
* <p>
Expand All @@ -52,7 +83,7 @@ public void onUpdate(SplitClient client, SdkUpdateMetadata metadata) {
* @param client the Split client instance
* @param metadata the typed metadata containing cache information
*/
public void onReadyFromCache(SplitClient client, SdkReadyFromCacheMetadata metadata) {
public void onReadyFromCache(SplitClient client, SdkReadyMetadata metadata) {
// Default empty implementation
}

Expand All @@ -78,8 +109,7 @@ public void onUpdateView(SplitClient client, SdkUpdateMetadata metadata) {
* @param client the Split client instance
* @param metadata the typed metadata containing cache information
*/
public void onReadyFromCacheView(SplitClient client, SdkReadyFromCacheMetadata metadata) {
public void onReadyFromCacheView(SplitClient client, SdkReadyMetadata metadata) {
// Default empty implementation
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.split.android.client.events;

import androidx.annotation.Nullable;

/**
* Typed metadata for SDK_READY and SDK_READY_FROM_CACHE events.
* <p>
* Contains information about the cache state when the SDK becomes ready.
*/
public final class SdkReadyMetadata {

@Nullable
private final Boolean mInitialCacheLoad;

@Nullable
private final Long mLastUpdateTimestamp;

/**
* Creates a new SdkReadyMetadata instance.
*
* @param initialCacheLoad true if this is an initial cache load with no usable cache, or null if not available
* @param lastUpdateTimestamp the last successful cache timestamp in milliseconds since epoch, or null if not available
*/
public SdkReadyMetadata(@Nullable Boolean initialCacheLoad, @Nullable Long lastUpdateTimestamp) {
mInitialCacheLoad = initialCacheLoad;
mLastUpdateTimestamp = lastUpdateTimestamp;
}

/**
* Returns whether this is an initial cache load with no usable cache.
* <p>
* This is true when the SDK starts without any prior cached data (fresh install),
* meaning data was fetched from the server for the first time.
*
* @return true if initial cache load, false otherwise, or null if not available
*/
@Nullable
public Boolean isInitialCacheLoad() {
return mInitialCacheLoad;
}

/**
* Returns the last successful cache timestamp in milliseconds since epoch.
*
* @return the timestamp, or null if not available
*/
@Nullable
public Long getLastUpdateTimestamp() {
return mLastUpdateTimestamp;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.split.android.client.events;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class SdkReadyMetadataTest {

@Test
public void isInitialCacheLoadReturnsNullWhenConstructedWithNull() {
SdkReadyMetadata metadata = new SdkReadyMetadata(null, null);

assertNull(metadata.isInitialCacheLoad());
}

@Test
public void isInitialCacheLoadReturnsTrueWhenConstructedWithTrue() {
SdkReadyMetadata metadata = new SdkReadyMetadata(true, null);

assertTrue(metadata.isInitialCacheLoad());
}

@Test
public void isInitialCacheLoadReturnsFalseWhenConstructedWithFalse() {
SdkReadyMetadata metadata = new SdkReadyMetadata(false, null);

assertFalse(metadata.isInitialCacheLoad());
}

@Test
public void getLastUpdateTimestampReturnsNullWhenConstructedWithNull() {
SdkReadyMetadata metadata = new SdkReadyMetadata(null, null);

assertNull(metadata.getLastUpdateTimestamp());
}

@Test
public void getLastUpdateTimestampReturnsValueWhenConstructedWithValue() {
long timestamp = 1704067200000L;
SdkReadyMetadata metadata = new SdkReadyMetadata(null, timestamp);

assertEquals(Long.valueOf(timestamp), metadata.getLastUpdateTimestamp());
}

@Test
public void bothValuesReturnCorrectlyWhenBothAreSet() {
long timestamp = 1704067200000L;
SdkReadyMetadata metadata = new SdkReadyMetadata(true, timestamp);

assertTrue(metadata.isInitialCacheLoad());
assertEquals(Long.valueOf(timestamp), metadata.getLastUpdateTimestamp());
}

@Test
public void bothValuesReturnCorrectlyWhenInitialCacheLoadIsFalse() {
long timestamp = 1704067200000L;
SdkReadyMetadata metadata = new SdkReadyMetadata(false, timestamp);

assertFalse(metadata.isInitialCacheLoad());
assertEquals(Long.valueOf(timestamp), metadata.getLastUpdateTimestamp());
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,20 @@ private void propagateTriggeredEvents(ISplitEventsManager splitEventsManager) {
}
}
}

/**
* Checks if an external event has already been triggered in any registered manager.
*
* @param event the event to check
* @return true if the event has already been triggered in any manager, false otherwise
*/
@Override
public boolean eventAlreadyTriggered(SplitEvent event) {
for (ISplitEventsManager manager : mManagers.values()) {
if (manager.eventAlreadyTriggered(event)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@ public interface ISplitEventsManager {
* @param metadata the event metadata, can be null
*/
void notifyInternalEvent(SplitInternalEvent internalEvent, @Nullable EventMetadata metadata);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we are using "Split" name? I thought it suppose to be ISdkEventsManager

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, we already had SplitInternalEvent so I kept it to reduce changes. But we could rename it, it's not breaking.

/**
* Checks if an external event has already been triggered.
*
* @param event the event to check
* @return true if the event has already been triggered (reached its max executions), false otherwise
*/
boolean eventAlreadyTriggered(SplitEvent event);
}
Loading
Loading