Slide 1

Slide 1 text

#androidjetpack What’s New in Jetpack Jaesung Lee GDSC HUFS

Slide 2

Slide 2 text

Adobe Stock#243026154 GDSC HUFS HUFS I.C.E Android Developer Jaesung Lee @jdoongxx @JaesungLeee

Slide 3

Slide 3 text

https://www.youtube.com/watch?v=jTd82lcuHTU Google I/O 22

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Activity AppCompat Camera Compose DataBinding Fragment Hilt LifeCycle MaterialDesignComponent Navigation Paging Room Test WorkManager WindowManager DataStore Prerference BenchMark Core Emoji2 RecyclerView ConstraintLayout Media Macrobenchmark JankStats SavedState BaselineProfiles https://developer.android.com/jetpack/androidx/explorer?case=all

Slide 7

Slide 7 text

Rewritten from Java to Kotlin Support for Kotlin! Google I/O 2017 https://android-developers.googleblog.com/2017/05/android-announces-support-for-kotlin.html

Slide 8

Slide 8 text

TimeLine 2017 Kotlin 2018 KTX Android Jetpack Official Language

Slide 9

Slide 9 text

TimeLine 2017 Kotlin 2018 KTX Android Jetpack 2019 BenchMark Kotlin first! Official Language Many New Jetpack APIs and features will be offered first in Kotlin!

Slide 10

Slide 10 text

TimeLine 2017 Kotlin 2018 KTX Android Jetpack 2019 BenchMark Kotlin first! Official Language 2020 Paging3 Window DataStore https://developer.android.com/jetpack/androidx/versions/alpha-channel#august_11_2020 Compose

Slide 11

Slide 11 text

TimeLine 2017 Kotlin 2018 KTX 2019 BenchMark 2020 Paging3 2022 Navigation 2.4 Annotation 1.4 Collection 1.2 Fragment 1.4 Activity 1.4 Partially rewritten by Kotlin!

Slide 12

Slide 12 text

// Navigation.java public final class Navigation { @NonNull public static View.OnClickListener createNavigateOnClickListener( @IdRes final int resId) { return createNavigateOnClickListener(resId, null); } @NonNull public static View.OnClickListener createNavigateOnClickListener( @IdRes final int resId, @Nullable final Bundle args) { return new View.OnClickListener() { @Override public void onClick(View view) { findNavController(view).navigate(resId, args); } }; } }

Slide 13

Slide 13 text

// Navigation.kt public object Navigation { @JvmStatic @JvmOverloads public fun createNavigateOnClickListener( @IdRes resId: Int, args: Bundle? = null ): View.OnClickListener { return View.OnClickListener { view -> findNavController(view).navigate(resId, args) } } }

Slide 14

Slide 14 text

TimeLine 2017 Kotlin 2018 KTX Android Jetpack 2019 BenchMark Kotlin first! Official Language 2020 Paging3 Window DataStore Compose https://developer.android.com/jetpack/androidx/versions/alpha-channel#august_11_2020 2022 Navigation 2.4 Annotation 1.4 Collection 1.2 Fragment 1.4 Activity 1.4 2023 (?) Room 2.5 Work 2.8 SavedState 1.2 …

Slide 15

Slide 15 text

// WorkManager 2.7.1 val constraints = Constraints.Builder() .setRequiresCharging(true) .setRequiresBatteryNotLow(true) .setRequiresDeviceIdle(true) .build() // WorkManager 2.8.0-alpha02 val constraints = Constraints( requiresCharging = true, requiresBatteryNotLow = true, requiresDeviceIdle = true, ) Enhanced APIs for Kotlin users!

Slide 16

Slide 16 text

Room, WorkManager, and more… Android Architecture Components

Slide 17

Slide 17 text

androidx.room:room:2.4.2 Room Stable Database persistence layer designed for usability, safety, and testability

Slide 18

Slide 18 text

Room Stable Auto Migrations Support for Kotlin 1.6 Room written in Kotlin starting from 2.5.0 Performance Improvements with KSP in 2.4.0 Room-Paging Support (Paging 3.0) Relational Query Methods androidx.room:room:2.4.2 https://developer.android.com/jetpack/androidx/releases/room#2.4.0

Slide 19

Slide 19 text

// Auto Migrations @Database( version = 2, entities = [User::class], autoMigrations = [ AutoMigration ( from = 1, to = 2, spec = AppDatabase.MyAutoMigration::class ) ] ) abstract class AppDatabase : RoomDatabase() { @RenameTable(fromTableName = "User", toTableName = "AppUser") class MyAutoMigration : AutoMigrationSpec } https://developer.android.com/training/data-storage/room/migrating-db-versions#automated

Slide 20

Slide 20 text

// Supports multimap return types // like Map, SparseArray, LongSparseArray, etc. // 1:1 Relation Map @Query("SELECT * FROM Song JOIN Artist ON Song.artistId = Artist.artistId") fun getSongAndArtist(): Map // 1:N Relation Map @Query("SELECT * FROM Artist JOIN Album ON Artist.id = Album.artistId") fun getArtistAndAlbums(): Map> https://developer.android.com/training/data-storage/room/accessing-data#multimap

Slide 21

Slide 21 text

androidx.paging:paging:3.1.1 Paging Stable Load and display small chunks of data to improve network and system resources consumption.

Slide 22

Slide 22 text

Paging Stable Stable support for Rx and Guava integrations Improvements to handling of invalid or stale data More comprehensive callbacks New introductory codelab for Paging 3 androidx.paging:paging:3.1.1 https://developer.android.com/jetpack/androidx/releases/paging#3.1.0

Slide 23

Slide 23 text

androidx.navigation:navigation:2.4.1 Navigation Stable Framework for navigating between destinations within an app, now with multiple backstacks

Slide 24

Slide 24 text

Navigation Stable Integration between Navigation with Jetpack Compose Support for Multiple Back Stacks Support for two-pane layouts All artifacts rewritten in Kotlin androidx.navigation:navigation:2.4.2 https://developer.android.com/jetpack/androidx/releases/navigation#2.4.0

Slide 25

Slide 25 text

Adobe Stock#243026154 Phone Tablet

Slide 26

Slide 26 text

class NavigationActivity : AppCompatActivity(R.layout.activity_navigation) https://github.com/CesarValiente/navigation-foldable

Slide 27

Slide 27 text

https://github.com/CesarValiente/navigation-foldable class TwoPaneFragment : AbstractListDetailFragment() { override fun onCreateListPaneView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ListPaneBinding.inflate(inflater, container, false) } override fun onListPaneViewCreated(view: View, savedInstanceState: Bundle?) { oneFragmentButton.setOnClickListener { openDetails(R.id.one_fragment) } } ... }

Slide 28

Slide 28 text

class TwoPaneFragment : AbstractListDetailFragment() { ... private fun openDetails(destinationId: Int) { val detailNavController = detailPaneNavHostFragment.navController detailNavController.navigate( resId = destinationId, args = null, navOptions = navOptions { popUpTo(detailNavController.graph.startDestinationId) { inclusive = true } } ) slidingPaneLayout.open() } override fun onCreateDetailPaneNavHostFragment(): NavHostFragment { return NavHostFragment.create(R.navigation.detail_pane_nav_graph) } } https://github.com/CesarValiente/navigation-foldable

Slide 29

Slide 29 text

class OneFragment : Fragment(R.layout.one_fragment) class TwoFragment : Fragment(R.layout.two_fragment) class ThreeFragment : Fragment(R.layout.three_fragment) https://github.com/CesarValiente/navigation-foldable

Slide 30

Slide 30 text

androidx.datastore:datastore:1.0.0 DataStore Stable Data storage solution that provides a simple, robust alternative to SharedPreferences

Slide 31

Slide 31 text

DataStore Stable MAD Skills: DataStore goo.gle/mad-skills-datastore How to migrate from SharedPreferences to Proto DataStore. d.android.com/codelabs/android-proto-datastore#7 androidx.datastore:datastore:1.0.0 https://developer.android.com/jetpack/androidx/releases/datastore#1.0.0

Slide 32

Slide 32 text

Lifecycle Stable Deprecated @OnLifecycleEvent Integration between ViewModel and Jetpack Compose Restartable Lifecycle-aware coroutines androidx.lifecycle:lifecycle:2.4.1 https://developer.android.com/jetpack/androidx/releases/lifecycle RC androidx.lifecycle:lifecycle:2.5.0+ ViewModel CreationExtras

Slide 33

Slide 33 text

// You can use DefaultLifecycleObserver or LifecycleEventObserver instead. - class MyObserver(...) : LifecycleObserver { + class MyObserver(...) : DefaultLifecycleObserver { - @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onResume() { ... } - @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun onPause() { ... } } https://developer.android.com/training/data-storage/room/accessing-data#multimap Stable

Slide 34

Slide 34 text

// Restartable Lifecycle-aware coroutines viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.someDataFlow.collect { // Process item } } } https://developer.android.com/topic/libraries/architecture/coroutines#restart Stable

Slide 35

Slide 35 text

// Lifecycle-aware flow collection viewLifecycleOwner.lifecycleScope.launch { exampleProvider.exampleFlow() .flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED) .collect { // Process the value. } } viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { launch { flow1.collect { /* Process the value. */ } } launch { flow2.collect { /* Process the value. */ } } } } https://developer.android.com/topic/libraries/architecture/coroutines#lifecycle-aware Stable

Slide 36

Slide 36 text

// current class MyActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels() ... } class MyViewModel( private val savedStateHandle: SavedStateHandle, ) : ViewModel() { fun loadData(id: String) { ... } } RC

Slide 37

Slide 37 text

// current class MyActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels() override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory { return super.getDefaultViewModelProviderFactory() // SavedStateViewModelFactory } } class MyViewModel( private val savedStateHandle: SavedStateHandle, ) : ViewModel() { fun loadData(id: String) { ... } } RC

Slide 38

Slide 38 text

class MyActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels() } class MyViewModel( private val savedStateHandle: SavedStateHandle, + private val id: String, ) : ViewModel() { - fun loadData(id: String) { - ... - } } https://developer.android.com/topic/libraries/architecture/coroutines#restart RC

Slide 39

Slide 39 text

class MyActivity : AppCompatActivity() { + private val key = object : CreationExtras.Key {} private val factory = object : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( modelClass: Class, + extras: CreationExtras, ): T { val savedStateHandle = extras.createSavedStateHandle() + val id = extras[key].orEmpty() return MainViewModel( savedStateHandle = savedStateHandle, + id = id, ) as T } } override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory = factory ... } https://pluu.github.io/blog/android/2022/03/12/creationextras/ RC

Slide 40

Slide 40 text

MAD Skills : Architecture Stable Materials on the best practices for Modern Android Development (MAD) http://goo.gle/mad-skills-architecture

Slide 41

Slide 41 text

Baseline profiles, JankStats, Benchmarking and more.. Performance

Slide 42

Slide 42 text

androidx.metrics:metrics-performance JankStats Alpha Track and analyze jank performance problems in your app’s UI

Slide 43

Slide 43 text

JankStats Alpha Compatible down to API Level 16 Identifies performance issues using internal heuristics Provides UI context to attribute data to user states and actions Reports results on every frame via a listener androidx.metrics:metrics-performance:1.0.0-alpha01 https://developer.android.com/topic/performance/jankstats

Slide 44

Slide 44 text

androidx.profilesinstaller:profileinstaller:1.1.0 Baseline Profiles Stable Create profiles for your app that prepopulate ahead of time compilation tracest to reduce startup times and reduce jank

Slide 45

Slide 45 text

Baseline Profiles Stable Provide custom profile rules in apps and libraries Startup and jank performance improvements Profiles added to popular Jetpack libraries androidx.profileinstaller:profileinstaller:1.1.0 https://developer.android.com/jetpack/androidx/releases/navigation#2.4.0

Slide 46

Slide 46 text

androidx.benchmark:benchmark-macro:1.1.0 Macrobenchmark Stable Accurately measure app startup and scrolling performance, both locally and in CI

Slide 47

Slide 47 text

Macrobenchmark Stable Now supports down to API Level 23 Add custom trace-based timing measurement with TraceSectionMetric Allow detection of audio underruns with AudioUnderrunMetric Added BaselineProfileRule to generate profiles for critical workflows androidx.benchmark:benchmark-macro:1.1.0 https://developer.android.com/topic/performance/benchmarking/macrobenchmark-overview

Slide 48

Slide 48 text

androidx.tracing:tracing:1.1.0 Tracing Stable Write trace events to the system trace buffer

Slide 49

Slide 49 text

LargeScreen, WindowManager, AppCompat and more.. User Interface

Slide 50

Slide 50 text

androidx.slidingpanelayout:slidingpanelayout:1.2.0 SlidingPaneLayout Stable supports showing two panes side by side on larger devices and foldables, while automatically adapting to show only one pane at a time on smaller devices

Slide 51

Slide 51 text

SlidingPaneLayout Stable Support for two-pane UX For Large Screen androidx.slidingpanelayout :slidingpanelayout:1.2.0 https://d.android.com/jetpack/androidx/releases/slidingpanelayout#1.2.0

Slide 52

Slide 52 text

https://developer.android.com/guide/topics/ui/layout/twopane

Slide 53

Slide 53 text

https://developer.android.com/guide/topics/ui/layout/twopane

Slide 54

Slide 54 text

// A method on the Fragment that owns the SlidingPaneLayout, // called by the adapter when an item is selected. fun openDetails(itemId: Int) { childFragmentManager.commit { setReorderingAllowed(true) replace(R.id.detail_container, bundleOf("itemId" to itemId)) // If we're already open and the detail pane is visible, // crossfade between the fragments. if (binding.slidingPaneLayout.isOpen) { setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) } } binding.slidingPaneLayout.open() } https://developer.android.com/guide/topics/ui/layout/twopane

Slide 55

Slide 55 text

androidx.window:window:1.0.0 WindowManager Stable Support new device form factors and multi-window environments

Slide 56

Slide 56 text

Supports foldable phones to adjust how content is displayed Smart layout avoids placing content in occluded areas Already integrated into SlidingPaneLayout WindowManager Stable androidx.window:window:1.0.0 https://developer.android.com/jetpack/androidx/releases/window#1.0.0

Slide 57

Slide 57 text

androidx.preference:preference:1.2.0 Preference Stable Support users to change the functionality and behavior of an application

Slide 58

Slide 58 text

Stable Preference Support for two-pane preference androidx.preference:preference:1.2.0 https://d.android.com/jetpack/androidx/releases/preference#1.2.0 https://github.com/CesarValiente/preferences-foldable

Slide 59

Slide 59 text

Adobe Stock#243026154 Phone Tablet

Slide 60

Slide 60 text

class PreferenceActivity : AppCompatActivity(R.layout.activity_preference) class TwoPanePreference : PreferenceHeaderFragmentCompat() { override fun onCreatePreferenceHeader(): PreferenceFragmentCompat { return HeaderPreference() } } class HeaderPreference : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.preferences, rootKey) } } https://github.com/CesarValiente/preferences-foldable

Slide 61

Slide 61 text

https://github.com/CesarValiente/preferences-foldable

Slide 62

Slide 62 text

androidx.dragandrop:draganddrop DragAndDrop Stable Accept drag-and-drop data with a consistent user experience

Slide 63

Slide 63 text

DragAndDrop Stable Simplifies ingesting dropped data Drop target highlighting androidx.draganddrop:draganddrop:1.0.0 https://developer.android.com/jetpack/androidx/releases/draganddrop#1.0.0

Slide 64

Slide 64 text

// Use the DragStartHelper class to easily support initiating drag and drop in response to // both long press and mouse drag events. Note the call to attach() at the end. Without it, // the listener would never actually be attached to the view. Also note that attach() replaces // any OnTouchListener or OnLongClickListener already attached to the view. DragStartHelper(binding.textDragItem) { view, _ -> val text = (view as TextView).text // Create the ClipData to be shared val dragClipData = ClipData.newPlainText(/*label*/"Text", text) // Use the default drag shadow val dragShadowBuilder = View.DragShadowBuilder(view) // Initiate the drag. Note the DRAG_FLAG_GLOBAL, which allows for drag events to be istened // to by apps other than the source app. view.startDragAndDrop(dragClipData, dragShadowBuilder, null, DRAG_FLAG_GLOBAL) }.attach() https://github.com/android/user-interface-samples/tree/main/DragAndDrop

Slide 65

Slide 65 text

DropHelper.configureView( /* activity */ this, binding.textDropTarget, /* mimeTypes */ arrayOf( ClipDescription.MIMETYPE_TEXT_PLAIN, "application/x-arc-uri-list" // Support external items on Chrome OS Android 9 ), DropHelper.Options.Builder() .setHighlightColor(getColor(R.color.purple_300)) .build() ) { view, payload -> resetDropTarget() val item = payload.clip.getItemAt(0) val (_, remaining) = payload.partition { it == item } if (payload.clip.description.hasMimeType(MIMETYPE_TEXT_PLAIN) { binding.textDropTarget.text = item.text } // Allow the system to handle any remaining ClipData.Item objects if applicable // remaining } https://github.com/android/user-interface-samples/tree/main/DragAndDrop

Slide 66

Slide 66 text

androidx.appcompat:appcompat AppCompat Stable Access the latest foundational UI features from earlier API levels

Slide 67

Slide 67 text

AppCompat Stable Emoji2 integration allows default support for the latest emojis Custom locale selection backported from Tiramisu (Android 13) Uses Play splits to download additional locales androidx.appcompat:appcompat:1.4.2 https://developer.android.com/guide/topics/ui/look-and-feel/emoji2 androidx.appcompat:appcompat:1.6.0+

Slide 68

Slide 68 text

// Get app locales val locales: LocaleListCompat = AppCompatDelegate.getApplicationLocales() // Set app locales val locales: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY") // or LocaleListCompat.create(Locale.KOREA) AppCompatDelegate.setApplicationLocales(locales) https://developer.android.com/about/versions/13/features/app-languages#androidx-impl

Slide 69

Slide 69 text

override fun attachBaseContext(newBase: Context) { if (SDK_INT < 33) { // Preferred locales are managed automatically on API level 33+, // but we need to load them manually on earlier platform versions. val locales = loadLocalesFromPreferences() AppCompatDelegate.setApplicationLocales(locales) } super.attachBaseContext(newBase) } https://developer.android.com/about/versions/13/features/app-languages#androidx-impl

Slide 70

Slide 70 text

override fun attachBaseContext(newBase: Context) { if (SDK_INT < 33) { // Preferred locales are managed automatically on API level 33+, // but we need to load them manually on earlier platform versions. val locales = loadLocalesFromPreferences() AppCompatDelegate.setApplicationLocales(locales) } super.attachBaseContext(newBase) } https://developer.android.com/about/versions/13/features/app-languages#androidx-impl

Slide 71

Slide 71 text

androidx.constraintlayout:constraintlayout:2.2.0+ ConstraintLayout Stable Allows to create large and complex layouts with a flat view hierarchy

Slide 72

Slide 72 text

ConstraintLayout Alpha Support Grid Helper Androidx.constraintlayout: constraintlayout:2.2.0+ https://github.com/androidx/constraintlayout/wiki/What's-New-in-2.2

Slide 73

Slide 73 text

... ... https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 74

Slide 74 text

https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 75

Slide 75 text

https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 76

Slide 76 text

https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 77

Slide 77 text

https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 78

Slide 78 text

Now in 1.2 beta! Jetpack Compose

Slide 79

Slide 79 text

> 100 Top 1K apps

Slide 80

Slide 80 text

“All new Play Store features are built on top of this framework. Compose has been instrumental in unlocking better velocity and smoother landings for the app.” 01 “Compose makes it much easier to define our own components and to make their API contracts more explicit, flexible, and intuitive.” 02 “Jetpack Compose is a critical part of our technical strategy. The productivity gains are massive.” 03 Jetpack Compose Google Play Twitter AirBnB

Slide 81

Slide 81 text

Downloadable Fonts androidx.compose.ui:ui-text-google-fonts https://developer.android.com/jetpack/compose/text#downloadable-fonts Compose 1.2

Slide 82

Slide 82 text

val provider = GoogleFont.Provider( providerAuthority = "com.google.android.gms.fonts", providerPackage = "com.google.android.gms", certificates = R.array.com_google_android_gms_fonts_certs ) val MontserratFont = GoogleFont(name = "Montserrat") val MontserratFontFamily = FontFamily( Font(googleFont = MontserratFont, fontProvider = provider) ) Text( fontFamily = MontserratFontFamily, text = "Hello World!" ) https://github.com/android/compose-samples/pull/787

Slide 83

Slide 83 text

Nested Scrolling Interop Compose 1.2 androidx.compose.ui:ui:1.2.0-alpha08 + https://d.android.com/jetpack/compose/interop/compose-in-existing-ui#nested-scrolling

Slide 84

Slide 84 text

Scrolling Compose in View

Slide 85

Slide 85 text

Nested Scrolling Interop Phase 1: Scrolling compose in cooperating view (I5d1ac)

Slide 86

Slide 86 text

@ExperimentalComposeUiApi class ComposeInAndroidCoordinatorLayout : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.compose_in_android_coordinator_layout) findViewById(R.id.compose_view).apply { setContent { val nestedScrollInterop = rememberNestedScrollInteropConnection(this) LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop)) { items(20) { item -> Box(...) { Text(item.toString()) } } } } } } } Nested Scrolling Interop Phase 1: Scrolling compose in cooperating view (I5d1ac)

Slide 87

Slide 87 text

Scrolling View in Compose

Slide 88

Slide 88 text

Slide 89

Slide 89 text

val ToolbarHeight = 48.dp @Composable private fun NestedScrollInteropComposeParentWithAndroidChild() { val toolbarHeightPx = with(LocalDensity.current) { ToolbarHeight.roundToPx().toFloat() } val toolbarOffsetHeightPx = remember { mutableStateOf(0f) } val nestedScrollConnection = remember { object : NestedScrollConnection { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { val delta = available.y val newOffset = toolbarOffsetHeightPx.value + delta toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f) return Offset.Zero } } } ... } Nested Scrolling Interop Phase 2: A scrolling view child inside a compose parent (If7949)

Slide 90

Slide 90 text

@Composable private fun NestedScrollInteropComposeParentWithAndroidChild() { ... Box( Modifier .fillMaxSize() .nestedScroll(nestedScrollConnection) ) { TopAppBar( modifier = Modifier .height(ToolbarHeight) .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) }, title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") } ) ... } ) } Nested Scrolling Interop Phase 2: A scrolling view child inside a compose parent (If7949)

Slide 91

Slide 91 text

@Composable private fun NestedScrollInteropComposeParentWithAndroidChild() { ... AndroidView( { context -> LayoutInflater.from(context) .inflate(R.layout.android_in_compose_nested_scroll_interop, null).apply { with(findViewById(R.id.main_list)) { layoutManager = LinearLayoutManager(context, VERTICAL, false) adapter = NestedScrollInteropAdapter() } }.also { ViewCompat.setNestedScrollingEnabled(it, true) } }, modifier = Modifier.padding(top = ToolbarHeight).fillMaxWidth(), ) } Nested Scrolling Interop Phase 2: A scrolling view child inside a compose parent (If7949)

Slide 92

Slide 92 text

Compose in RecyclerView Compose 1.2 androidx.compose.ui:ui-1.2.0-beta02+ androidx.recyclerview:recyclerview:1.3.0-alpha02+ https://d.android.com/jetpack/compose/interop/compose-in-existing-ui#compose-recyclerview

Slide 93

Slide 93 text

// Compose 1.1 + RecyclerView 1.2 import androidx.compose.ui.platform.ComposeView class MyComposeAdapter : RecyclerView.Adapter() { override fun onCreateViewHolder(...): MyComposeViewHolder { return MyComposeViewHolder(ComposeView(parent.context)) } override fun onViewRecycled(holder: MyComposeViewHolder) { + holder.composeView.disposeComposition() } } class MyComposeViewHolder(val composeView: ComposeView) : RecyclerView.ViewHolder(composeView) { init { + composeView.setViewCompositionStrategy( + ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed + ) } } https://d.android.com/jetpack/compose/interop/compose-in-existing-ui#compose-recyclerview

Slide 94

Slide 94 text

// Compose 1.2 + RecyclerView 1.3 import androidx.compose.ui.platform.ComposeView class MyComposeAdapter : RecyclerView.Adapter() { override fun onCreateViewHolder(...): MyComposeViewHolder { return MyComposeViewHolder(ComposeView(parent.context)) } // override fun onViewRecycled(holder: MyComposeViewHolder) { // holder.composeView.disposeComposition() // } } class MyComposeViewHolder(val composeView: ComposeView) : RecyclerView.ViewHolder(composeView) { // init { // composeView.setViewCompositionStrategy( // ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed // ) // } } https://d.android.com/jetpack/compose/interop/compose-in-existing-ui#compose-recyclerview

Slide 95

Slide 95 text

Lazy Layouts Compose 1.2 androidx.compose.foundation:foundation https://developer.android.com/jetpack/compose/lists Lazy Layouts in Compose

Slide 96

Slide 96 text

@OptIn(ExperimentalFoundationApi::class) LazyVerticalGrid( columns = GridCells.Fixed(2), verticalArrangement = Arragement.spaceBy(16.dp), horizontalArrangement = Arragement.spaceBy(16.dp), ) { items(data) { item -> Item(item) } } https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 97

Slide 97 text

// New! LazyHorizontalGrid( rows = GridCells.Fixed(2), verticalArrangement = Arragement.spaceBy(16.dp), horizontalArrangement = Arragement.spaceBy(16.dp), ) { items(data) { item -> Item(item) } } https://speakerdeck.com/fornewid/whats-new-in-jetpack-2022

Slide 98

Slide 98 text

Not Available Instead of androidx.recyclerview.widget. StaggeredGridLayoutManager https://issuetracker.google.com/issues/182882362 Staggered Grids

Slide 99

Slide 99 text

Text Magnifier Compose 1.2 androidx.compose.foundation:foundation I30b38, b/139320979

Slide 100

Slide 100 text

Show Layout Bounds immediately Compose 1.2 androidx.compose.ui:ui:1.2.0-beta03 I843d5, b/225937688

Slide 101

Slide 101 text

Tools What’s New in Android Studio Live Edit Recomposition debugging Compose Animation Preview

Slide 102

Slide 102 text

Recommended

Slide 103

Slide 103 text

Thank you! Android Developer / GDSC HUFS HUFS I.C.E @jdoongxx @JaesungLeee https://speakerdeck.com/jaesungleee/whats-new-in-jetpack-2022 [email protected] https://d.android.com/jetpack https://www.youtube.com/watch?v =jTd82lcuHTU&t=242s Resources Jaesung Lee