Skip to content

Commit

Permalink
Merge pull request #652 from prudrabhat/uiservice_errorhandling
Browse files Browse the repository at this point in the history
Use a supervisor job and exception hander in UIService
  • Loading branch information
praveek authored May 15, 2024
2 parents b242087 + 330dd07 commit 1a7506e
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,41 @@
package com.adobe.marketing.mobile.services.ui

import android.app.Application
import com.adobe.marketing.mobile.services.Log
import com.adobe.marketing.mobile.services.ServiceConstants
import com.adobe.marketing.mobile.services.ui.alert.AlertPresentable
import com.adobe.marketing.mobile.services.ui.common.AppLifecycleProvider
import com.adobe.marketing.mobile.services.ui.floatingbutton.FloatingButtonPresentable
import com.adobe.marketing.mobile.services.ui.floatingbutton.FloatingButtonViewModel
import com.adobe.marketing.mobile.services.ui.message.InAppMessagePresentable
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob

/**
* UI Service implementation for AEP SDK
*/
internal class AEPUIService : UIService {
companion object {
private const val LOG_TAG = "AEPUIService"
}

private var presentationDelegate: PresentationDelegate? = null

private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
Log.error(
ServiceConstants.LOG_TAG,
LOG_TAG,
"An error occurred while processing the presentation: ${throwable.message}",
throwable
)
}

private val mainScope by lazy {
CoroutineScope(Dispatchers.Main + SupervisorJob() + exceptionHandler)
}

@Suppress("UNCHECKED_CAST")
override fun <T : Presentation<T>> create(
presentation: T,
Expand All @@ -44,7 +65,7 @@ internal class AEPUIService : UIService {
presentationDelegate,
presentationUtilityProvider,
AppLifecycleProvider.INSTANCE,
CoroutineScope(Dispatchers.Main)
mainScope
) as Presentable<T>
}

Expand All @@ -53,7 +74,8 @@ internal class AEPUIService : UIService {
presentation,
presentationDelegate,
presentationUtilityProvider,
AppLifecycleProvider.INSTANCE
AppLifecycleProvider.INSTANCE,
mainScope
) as Presentable<T>
}

Expand All @@ -63,7 +85,8 @@ internal class AEPUIService : UIService {
FloatingButtonViewModel(presentation.settings),
presentationDelegate,
presentationUtilityProvider,
AppLifecycleProvider.INSTANCE
AppLifecycleProvider.INSTANCE,
mainScope
) as Presentable<T>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
import com.adobe.marketing.mobile.services.ui.alert.views.AlertScreen
import com.adobe.marketing.mobile.services.ui.common.AEPPresentable
import com.adobe.marketing.mobile.services.ui.common.AppLifecycleProvider
import kotlinx.coroutines.CoroutineScope

/**
* Represents an Alert presentable.
Expand All @@ -33,12 +34,14 @@ internal class AlertPresentable(
val alert: Alert,
presentationDelegate: PresentationDelegate?,
presentationUtilityProvider: PresentationUtilityProvider,
appLifecycleProvider: AppLifecycleProvider
appLifecycleProvider: AppLifecycleProvider,
mainScope: CoroutineScope
) : AEPPresentable<Alert>(
alert,
presentationUtilityProvider,
presentationDelegate,
appLifecycleProvider
appLifecycleProvider,
mainScope
) {
override fun getContent(activityContext: Context): ComposeView {
return ComposeView(activityContext).apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import com.adobe.marketing.mobile.services.ui.Presentation
import com.adobe.marketing.mobile.services.ui.PresentationDelegate
import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.lang.ref.WeakReference
import java.util.Random
Expand All @@ -52,10 +51,10 @@ internal abstract class AEPPresentable<T : Presentation<T>> :
private val presentation: Presentation<T>
private val presentationUtilityProvider: PresentationUtilityProvider
private val presentationDelegate: PresentationDelegate?
private val mainScope: CoroutineScope
private val appLifecycleProvider: AppLifecycleProvider
private val presentationObserver: PresentationObserver
private val activityCompatOwnerUtils: ActivityCompatOwnerUtils
private val mainScope: CoroutineScope
protected val presentationStateManager: PresentationStateManager

@VisibleForTesting internal val contentIdentifier: Int = Random().nextInt()
Expand All @@ -70,15 +69,16 @@ internal abstract class AEPPresentable<T : Presentation<T>> :
presentation: Presentation<T>,
presentationUtilityProvider: PresentationUtilityProvider,
presentationDelegate: PresentationDelegate?,
appLifecycleProvider: AppLifecycleProvider
appLifecycleProvider: AppLifecycleProvider,
mainScope: CoroutineScope
) : this(
presentation,
presentationUtilityProvider,
presentationDelegate,
appLifecycleProvider,
PresentationStateManager(),
ActivityCompatOwnerUtils(),
CoroutineScope(Dispatchers.Main),
mainScope,
PresentationObserver.INSTANCE
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
import com.adobe.marketing.mobile.services.ui.common.AEPPresentable
import com.adobe.marketing.mobile.services.ui.common.AppLifecycleProvider
import com.adobe.marketing.mobile.services.ui.floatingbutton.views.FloatingButtonScreen
import kotlinx.coroutines.CoroutineScope

/**
* Represents a presentable floating button presentation
Expand All @@ -35,12 +36,14 @@ internal class FloatingButtonPresentable(
private val floatingButtonViewModel: FloatingButtonViewModel,
presentationDelegate: PresentationDelegate?,
presentationUtilityProvider: PresentationUtilityProvider,
appLifecycleProvider: AppLifecycleProvider
appLifecycleProvider: AppLifecycleProvider,
mainScope: CoroutineScope
) : AEPPresentable<FloatingButton>(
floatingButton,
presentationUtilityProvider,
presentationDelegate,
appLifecycleProvider
appLifecycleProvider,
mainScope
) {
// event handler for the floating button
private val floatingButtonEventHandler = object : FloatingButtonEventHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ internal class InAppMessagePresentable(
inAppMessage,
presentationUtilityProvider,
presentationDelegate,
appLifecycleProvider
appLifecycleProvider,
mainScope
) {

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.adobe.marketing.mobile.services.ui.InAppMessage
import com.adobe.marketing.mobile.services.ui.PresentationDelegate
import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
import com.adobe.marketing.mobile.services.ui.common.AppLifecycleProvider
import kotlinx.coroutines.CoroutineScope
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
Expand All @@ -40,12 +41,15 @@ class AlertPresentableTest {
@Mock
private lateinit var mockAppLifecycleProvider: AppLifecycleProvider

@Mock
private lateinit var mockScope: CoroutineScope

private lateinit var alertPresentable: AlertPresentable

@Before
fun setUp() {
MockitoAnnotations.openMocks(this)
alertPresentable = AlertPresentable(mockAlert, mockPresentationDelegate, mockPresentationUtilityProvider, mockAppLifecycleProvider)
alertPresentable = AlertPresentable(mockAlert, mockPresentationDelegate, mockPresentationUtilityProvider, mockAppLifecycleProvider, mockScope)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.adobe.marketing.mobile.services.ui.InAppMessage
import com.adobe.marketing.mobile.services.ui.PresentationDelegate
import com.adobe.marketing.mobile.services.ui.PresentationUtilityProvider
import com.adobe.marketing.mobile.services.ui.common.AppLifecycleProvider
import kotlinx.coroutines.CoroutineScope
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
Expand Down Expand Up @@ -47,6 +48,9 @@ class FloatingButtonPresentableTest {
@Mock
private lateinit var mockFloatingButtonSettings: FloatingButtonSettings

@Mock
private lateinit var mockScope: CoroutineScope

private lateinit var floatingButtonPresentable: FloatingButtonPresentable

@Before
Expand All @@ -61,7 +65,8 @@ class FloatingButtonPresentableTest {
mockFloatingButtonViewModel,
mockPresentationDelegate,
mockPresentationUtilityProvider,
mockAppLifecycleProvider
mockAppLifecycleProvider,
mockScope
)

verify(mockFloatingButtonViewModel).onGraphicUpdate(mockFloatingButtonSettings.initialGraphic)
Expand Down

0 comments on commit 1a7506e

Please sign in to comment.