SplashActivity Handler 제거, SplashScreen API + ViewModel + 테스트로 교체#400
Conversation
- androidx.core:core-splashscreen 도입, windowBackground 방식 제거 - SplashViewModel: Handler → viewModelScope + delay, isReady/navigateEvent StateFlow/SharedFlow - SplashActivity: @androidentrypoint + viewModels(), setKeepOnScreenCondition으로 splash 유지 - SplashViewModelTest: 4개 케이스 (초기값, 1초 전, 1초 후 isReady, navigateEvent emit) - activity_splash.xml 삭제 (빈 레이아웃)
|
Warning Review limit reached
More reviews will be available in 3 minutes and 51 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThe PR adds AndroidX splash-screen support, introduces a ChangesSplash screen startup flow
Sequence Diagram(s)sequenceDiagram
participant SplashActivity
participant "AndroidX SplashScreen" as AndroidXSplashScreen
participant SplashViewModel
participant LoginActivity
SplashActivity->>AndroidXSplashScreen: installSplashScreen()
SplashActivity->>SplashViewModel: read isReady in setKeepOnScreenCondition()
SplashViewModel-->>SplashActivity: isReady becomes true after SPLASH_DELAY
SplashActivity->>SplashViewModel: collect navigateEvent in repeatOnLifecycle(STARTED)
SplashViewModel-->>SplashActivity: emit navigateEvent
SplashActivity->>LoginActivity: startActivity(Intent.FLAG_ACTIVITY_NO_ANIMATION)
SplashActivity->>SplashActivity: finish()
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@app/src/main/java/com/runnect/runnect/presentation/splash/SplashViewModel.kt`:
- Around line 22-29: The splash navigation event can be lost when
`SplashActivity` stops collecting during rotation/backgrounding because
`SplashViewModel` uses `_navigateEvent` with no replay. Update
`SplashViewModel`’s `MutableSharedFlow` for `navigateEvent` to retain the
emission for late collectors, or add a fallback in `SplashActivity` when
collecting `navigateEvent` so navigation happens immediately if `isReady` is
already true. Keep the fix centered on the `init` block and `navigateEvent` flow
setup so resuming after lifecycle transitions cannot leave the splash screen
stuck.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d0fd9b8c-aa1d-4afb-83ff-17bd7e41ba56
📒 Files selected for processing (7)
app/build.gradleapp/src/main/java/com/runnect/runnect/presentation/splash/SplashActivity.ktapp/src/main/java/com/runnect/runnect/presentation/splash/SplashViewModel.ktapp/src/main/res/layout/activity_splash.xmlapp/src/main/res/values/themes.xmlapp/src/test/java/com/runnect/runnect/presentation/splash/SplashViewModelTest.ktgradle/libs.versions.toml
💤 Files with no reviewable changes (1)
- app/src/main/res/layout/activity_splash.xml
- windowSplashScreenAnimatedIcon 제거 (전체화면 이미지를 아이콘 슬롯에 잘못 사용한 것 수정)
- SplashActivity에 setContent { SplashScreen() } 추가 — splash.webp를 Compose Image로 렌더링
- setKeepOnScreenCondition { false }로 시스템 스플래시 즉시 해제 후 Compose 화면 표시
- windowSplashScreenBackground = M1(보라)로 시스템 스플래시 → Compose 전환 시 색상 연속성 유지
| finish() | ||
| }, DELAY_TIME) | ||
| } | ||
| setContent { |
There was a problem hiding this comment.
setContent { } — Compose 진입점
Activity에서 XML setContentView(R.layout.xxx)를 대체하는 Compose 진입점.
이 블록 안에 넘긴 @Composable 함수가 화면 전체를 그린다.
// 기존
setContentView(R.layout.activity_splash)
// Compose
setContent {
SplashScreen()
}핵심 개념:
setContent내부에서 Compose 런타임이 초기화되고,@Composable함수 호출 트리가 UI 트리로 변환됨ComponentActivity.setContent는androidx.activity.compose라이브러리가 제공 —AppCompatActivity를 상속해도 사용 가능
| import androidx.compose.ui.res.painterResource | ||
| import com.runnect.runnect.R | ||
|
|
||
| @Composable |
There was a problem hiding this comment.
@Composable — Compose 함수 선언
이 어노테이션이 붙은 함수는 UI를 **기술(describe)**하는 단위.
기존 XML inflate + View 참조 방식 대신 함수 호출 트리가 UI 구조가 된다.
// 기존: XML을 inflate하고 View에 데이터 바인딩
val binding = ActivitySplashBinding.inflate(layoutInflater)
// Compose: 함수 = UI
@Composable
fun SplashScreen() { ... }핵심 개념:
@Composable함수는 일반 함수처럼 호출하지만, Compose 런타임이 호출 트리를 추적해 상태 변화 시 변경된 부분만 다시 그림(recomposition)- 반환값이 없음 — 함수가 UI를 직접 '그리는' 것이 아니라 런타임에 UI 트리를 '기술'하는 것
@Composable함수는 반드시 다른@Composable스코프에서 호출해야 함
| Image( | ||
| painter = painterResource(id = R.drawable.splash), | ||
| contentDescription = null, | ||
| modifier = Modifier.fillMaxSize(), |
There was a problem hiding this comment.
Modifier — Compose의 레이아웃/스타일 체이닝
기존 View XML의 layout_width, layout_height, padding, background 등 속성을 코드로 체이닝하는 방식.
<!-- 기존 XML -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent" />// Compose
Image(
modifier = Modifier.fillMaxSize() // match_parent × match_parent
)핵심 개념:
Modifier는 순서가 중요함 —fillMaxSize().padding(16.dp)와padding(16.dp).fillMaxSize()는 다른 결과- 각 Composable의
modifier파라미터로 전달 — 컴포넌트 자체 크기·위치·동작을 외부에서 제어하는 패턴 fillMaxSize()=match_parent/wrapContentSize()=wrap_content/size(100.dp)= 고정 크기
| painter = painterResource(id = R.drawable.splash), | ||
| contentDescription = null, | ||
| modifier = Modifier.fillMaxSize(), | ||
| contentScale = ContentScale.FillBounds, |
There was a problem hiding this comment.
ContentScale — Compose Image의 스케일링 방식
기존 ImageView의 android:scaleType 속성에 대응.
| ContentScale | ImageView scaleType | 동작 |
|---|---|---|
FillBounds |
fitXY |
비율 무시하고 컨테이너 꽉 채움 |
Crop |
centerCrop |
비율 유지, 짧은 축 기준으로 크롭 |
Fit |
fitCenter |
비율 유지, 긴 축 기준으로 맞춤 |
FillWidth |
fitStart(유사) |
너비 기준으로 채움 |
여기서 FillBounds를 선택한 이유: splash.webp가 정확히 기기 화면 비율(1440×3200)로 제작된 전체화면 이미지라 비율 왜곡이 발생해도 원본 windowBackground 렌더링 방식과 동일한 결과를 냄.
- 변경된 .kt 파일의 패키지를 추출해 --tests 필터 구성 - PR: 영향 범위 패키지 테스트만 실행 (unit + instrumented 동일 적용) - push to develop: 전체 테스트 실행 (안전망 유지)
--tests는 JVM 전용 옵션으로 connectedDebugAndroidTest에선 지원 안 됨. -Pandroid.testInstrumentationRunnerArguments.package 로 교체.
작업 배경
Handler방식을 제거하고 구조적 안전망을 추가변경 사항
SplashViewModel(신규)Handler제거 →viewModelScope + delay(1000ms),isReady: StateFlow,navigateEvent: SharedFlowSplashActivity@AndroidEntryPoint추가,installSplashScreen()+setContent { SplashScreen() }으로 Compose 전체화면 렌더링,lifecycleScope로 navigate 이벤트 수신SplashScreen(신규)splash.webp를 ComposeImage로 전체화면 렌더링SplashThemewindowBackground방식 제거 →Theme.SplashScreen부모,windowSplashScreenBackground = M1,postSplashScreenTheme연결activity_splash.xmllibs.versions.toml/build.gradleandroidx.core:core-splashscreen:1.0.1추가영향 범위
SplashActivity단일 화면에 한정LoginActivity로 이동하는 동작 동일, 시각적 변화 Before/After 영상으로 확인검증 매트릭스
isReady=false→setKeepOnScreenCondition유지)초기 상태에서 isReady는 false다•
1초 경과 전에는 isReady가 false다isReady=true)1초 경과 후 isReady가 true가 된다1초 후 navigateEvent가 emit된다Before / After 영상
splash_before.mp4
splash_after_new.mp4
Test Plan
🤖 Generated with Claude Code