Add overload of LazyLayout which accepts a lambda of LazyLayoutItemProvider

This overload allows users to write a more efficient code as the item provider can be updated without extra recomposition.

Relnote: Overload of LazyLayout added, it accepts a lambda of LazyLayoutItemProvider, not a plain object as it was before. The previous overload is deprecated.
Test: run lazy/layout tests
Change-Id: I42a5a3d5933deaccac5b5fc6df15c47194cf8b05
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 5383dcd7..8f3ee10 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -881,7 +881,8 @@
   }
 
   public final class LazyLayoutKt {
-    method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
+    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
+    method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(kotlin.jvm.functions.Function0<? extends androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider> itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
   }
 
   @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public sealed interface LazyLayoutMeasureScope extends androidx.compose.ui.layout.MeasureScope {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 2bdd519..4667dba 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -883,7 +883,8 @@
   }
 
   public final class LazyLayoutKt {
-    method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
+    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
+    method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void LazyLayout(kotlin.jvm.functions.Function0<? extends androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider> itemProvider, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState? prefetchState, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
   }
 
   @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public sealed interface LazyLayoutMeasureScope extends androidx.compose.ui.layout.MeasureScope {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutStateRestorationTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutStateRestorationTest.kt
index d05d1f1..eab253b 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutStateRestorationTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutStateRestorationTest.kt
@@ -299,20 +299,19 @@
         indexToKey: (Int) -> Any = { getDefaultLazyLayoutKey(it) },
         content: @Composable (Int) -> Unit
     ) {
-        LazyLayout(
-            itemProvider = remember(itemCount, indexToKey, content as Any) {
-                object : LazyLayoutItemProvider {
-                    override val itemCount: Int = itemCount()
+        val provider = remember(itemCount, indexToKey, content as Any) {
+            object : LazyLayoutItemProvider {
+                override val itemCount: Int = itemCount()
 
-                    @Composable
-                    override fun Item(index: Int, key: Any) {
-                        content(index)
-                    }
-
-                    override fun getKey(index: Int) = indexToKey(index)
+                @Composable
+                override fun Item(index: Int, key: Any) {
+                    content(index)
                 }
+
+                override fun getKey(index: Int) = indexToKey(index)
             }
-        ) { constraints ->
+        }
+        LazyLayout(itemProvider = { provider }) { constraints ->
             val placeables = mutableListOf<Placeable>()
             repeat(itemCount()) { index ->
                 if (itemIsVisible(index)) {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutTest.kt
index 7cedc56..cd762bf 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutTest.kt
@@ -163,7 +163,7 @@
             LazyLayout(itemProvider) {
                 val constraints = Constraints.fixed(100, 100)
                 val items = mutableListOf<Placeable>()
-                repeat(itemProvider.itemCount) { index ->
+                repeat(itemProvider().itemCount) { index ->
                     items.addAll(measure(index, constraints))
                 }
                 layout(100, 100) {
@@ -204,7 +204,7 @@
             LazyLayout(itemProvider) {
                 val constraints = Constraints.fixed(100, 100)
                 val items = mutableListOf<Placeable>()
-                repeat(itemProvider.itemCount) { index ->
+                repeat(itemProvider().itemCount) { index ->
                     items.addAll(measure(index, constraints))
                 }
                 layout(100, 100) {
@@ -463,7 +463,7 @@
             override fun getKey(index: Int) = stateList[index]
         }
         rule.setContent {
-            LazyLayout(itemProvider) { constraint ->
+            LazyLayout({ itemProvider }) { constraint ->
                 measure(0, constraint)
                 layout(100, 100) {}
             }
@@ -483,8 +483,8 @@
     private fun itemProvider(
         itemCount: () -> Int,
         itemContent: @Composable (Int) -> Unit
-    ): LazyLayoutItemProvider {
-        return object : LazyLayoutItemProvider {
+    ): () -> LazyLayoutItemProvider {
+        val provider = object : LazyLayoutItemProvider {
             @Composable
             override fun Item(index: Int, key: Any) {
                 itemContent(index)
@@ -492,5 +492,6 @@
 
             override val itemCount: Int get() = itemCount()
         }
+        return { provider }
     }
 }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayout.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayout.kt
index 3ad7f4f..6c08e89 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayout.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayout.kt
@@ -37,6 +37,12 @@
  * @param prefetchState allows to schedule items for prefetching
  * @param measurePolicy Measure policy which allows to only compose and measure needed items.
  */
+@Deprecated(
+    message = "Use an overload accepting a lambda prodicing an item provider instead",
+    replaceWith = ReplaceWith(
+        "LazyLayout({ itemProvider }, modifier, prefetchState, measurePolicy)"
+    )
+)
 @ExperimentalFoundationApi
 @Composable
 fun LazyLayout(
@@ -48,9 +54,19 @@
     LazyLayout({ itemProvider }, modifier, prefetchState, measurePolicy)
 }
 
+/**
+ * A layout that only composes and lays out currently needed items. Can be used to build
+ * efficient scrollable layouts.
+ *
+ * @param itemProvider lambda producing an item provider containing all the needed info about
+ * the items which could be used to compose and measure items as part of [measurePolicy].
+ * @param modifier to apply on the layout
+ * @param prefetchState allows to schedule items for prefetching
+ * @param measurePolicy Measure policy which allows to only compose and measure needed items.
+ */
 @ExperimentalFoundationApi
 @Composable
-internal fun LazyLayout(
+fun LazyLayout(
     itemProvider: () -> LazyLayoutItemProvider,
     modifier: Modifier = Modifier,
     prefetchState: LazyLayoutPrefetchState? = null,
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/LazyGrid.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/LazyGrid.kt
index b95b687..5cf5964 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/LazyGrid.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/LazyGrid.kt
@@ -127,7 +127,7 @@
             ),
         prefetchState = state.prefetchState,
         measurePolicy = measurePolicy,
-        itemProvider = itemProvider
+        itemProvider = { itemProvider }
     )
 }
 
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyList.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyList.kt
index 224af43..34254cc 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyList.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyList.kt
@@ -131,7 +131,7 @@
             ),
         prefetchState = state.prefetchState,
         measurePolicy = measurePolicy,
-        itemProvider = itemProvider
+        itemProvider = { itemProvider }
     )
 }