Status Update
Comments
an...@google.com <an...@google.com>
ap...@google.com <ap...@google.com> #2
This is a particularly hard device to come by - do you happen to have access to the device? If so could you provide us with the output of: adb shell dumpsys media.camera > info.txt
Thanks!
b9...@gmail.com <b9...@gmail.com> #3
Stacktrace:
Caused by: java.lang.IllegalArgumentException: Can not get supported output size under supported maximum for the format: 34
at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSupportedOutputSizes(SupportedSurfaceCombination.java:355)
at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSuggestedResolutions(SupportedSurfaceCombination.java:197)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions(Camera2DeviceSurfaceManager.java:198)
at androidx.camera.core.CameraX.calculateSuggestedResolutions(CameraX.java:943)
at androidx.camera.core.CameraX.bindToLifecycle(CameraX.java:293)
at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:227)
Below are some findings based on our debugging
When Dex is connected
previewConfig.getMaxResolution() is returning "731x411" as maxSize.
Inside Preview.Builder.build() -> Default_MAX_resolution is set to "CameraX.getSurfaceManager().getPreviewSize()" which is 731x411
this is being picked as maxSize.
While rendering maxSize is 731x411 and minSize is 640x480 and below are available outputSizes
0 = {Size@11860} "4032x3024"
1 = {Size@11861} "3984x2988"
2 = {Size@11862} "4032x2268"
3 = {Size@11863} "3024x3024"
4 = {Size@11864} "2976x2976"
5 = {Size@11865} "3840x2160"
6 = {Size@11866} "3264x2448"
7 = {Size@11867} "4032x1960"
8 = {Size@11868} "2880x2160"
9 = {Size@11869} "3264x1836"
10 = {Size@11870} "2160x2160"
11 = {Size@11871} "2560x1440"
12 = {Size@11872} "2224x1080"
13 = {Size@11873} "2048x1152"
14 = {Size@11874} "1920x1080"
15 = {Size@11875} "1440x1080"
16 = {Size@11876} "1088x1088"
17 = {Size@11877} "1280x720"
18 = {Size@11878} "1024x768"
19 = {Size@11879} "1056x704"
20 = {Size@11880} "960x720"
21 = {Size@11881} "960x540"
22 = {Size@11882} "720x720"
23 = {Size@11883} "800x450"
24 = {Size@11884} "720x480"
25 = {Size@11885} "640x480"
26 = {Size@11886} "352x288"
27 = {Size@11887} "320x240"
28 = {Size@11888} "256x144"
29 = {Size@11889} "176x144"
and couldn't find any size in this range.
When Dex not connected
minsize = 640x480
maxsize = 1920x1080
0 = {Size@11836} "4032x3024"
1 = {Size@11837} "3984x2988"
2 = {Size@11838} "4032x2268"
3 = {Size@11839} "3024x3024"
4 = {Size@11840} "2976x2976"
5 = {Size@11841} "3840x2160"
6 = {Size@11842} "3264x2448"
7 = {Size@11843} "4032x1960"
8 = {Size@11844} "2880x2160"
9 = {Size@11845} "3264x1836"
10 = {Size@11846} "2160x2160"
11 = {Size@11847} "2560x1440"
12 = {Size@11848} "2224x1080"
13 = {Size@11849} "2048x1152"
14 = {Size@11850} "1920x1080"
15 = {Size@11851} "1440x1080"
16 = {Size@11852} "1088x1088"
17 = {Size@11853} "1280x720"
18 = {Size@11854} "1024x768"
19 = {Size@11855} "1056x704"
20 = {Size@11856} "960x720"
21 = {Size@11857} "960x540"
22 = {Size@11858} "720x720"
23 = {Size@11859} "800x450"
24 = {Size@11860} "720x480"
25 = {Size@11861} "640x480"
26 = {Size@11862} "352x288"
27 = {Size@11863} "320x240"
28 = {Size@11864} "256x144"
29 = {Size@11865} "176x144"
and we have 12 available sizes in this range
Camera2DeviceSurfaceManager.java:: getPreviewSize()
mCameraSupportedSurfaceCombinationMap.get(cameraId).getSurfaceDefinition().getPreviewSize() = "1920x1080"
cameraId=0
an...@google.com <an...@google.com> #4
The issue root cause is that CameraX will default filter out sizes smaller than 640x480. For Preview, the max size will be limited to under display size. I checked the HW spec info for the issue related devices. Display size of FUJITSU F-04J/F-05J is 360x640. That will result int that no size exists in the conditions that is larger or equal to 640x480 and smaller or equal to 360x640.
A temporary workaround for this situation is to use Preview.Builder#setTargetResolution() to set a size smaller than 640x480 to bypass the problem.
For device FUJITSU arrowsM04, I checked its HW spec info and its display size I found is 1280x720. It seems that the problem should not exist in the device.
Could you confirm that the problem exist on arrowsM04 device? What will be the returned value when using Display#getRealSize to obtain the display size?
b9...@gmail.com <b9...@gmail.com> #5
> A temporary workaround for this situation is to use Preview.Builder#setTargetResolution() to set a size smaller than 640x480 to bypass the problem.
OK. I will try it.
> Could you confirm that the problem exist on arrowsM04 device?
We receive the crash report (Crashlytics) that this crash has occurred on arrowsM04.
We don't have this device so we can't confirm that the problem really exist on arrowsM04.
> What will be the returned value when using Display#getRealSize to obtain the display size?
We can't investigate it for the same reason.
Thank you.
an...@google.com <an...@google.com> #6
This issue happened on devices that the display size is smaller than 640x480. In original auto-resolution mechanism, supported sizes smaller than 640x480 will be default filter out.
The auto-resolution mechanism encodes the guaranteed configurations tables in CameraDevice#createCaptureSession(SessionConfiguration). It defines that the PREVIEW size is the small one of the device display size and 1080p. The PREVIEW size will be the maximal size limitation for Preview use case. The reason it limits the size to display size and 1080p is the stream output in display size or 1080p has been able to provide good enough preview quality. Therefore, auto-resolution mechanism will limit the selected size to be smaller than the small one of the device display size and 1080p.
With above two conditions, in this issue, all sizes smaller than 640x480 have been filter out, therefore, there is no size smaller than the display size 320x240 can be selected to use. And cause the exception.
Solution:
When the display size is smaller than 640x480, auto-resolution mechanism won't filter out those small sizes smaller than 640x480. This makes those small size be left and can be selected for the Preview use case on small display devices.
The solution has been merged and will be included in next CameraX release.
b9...@gmail.com <b9...@gmail.com> #7
Hello.
This crash still occurs.
- CAMERAX VERSION: 1.0.0-beta4
- ANDROID OS BUILD NUMBER: Android 7.1.1
- DEVICE NAME: FUJITSU F-02H
We receive following crash report from FUJITSU F-02H. So far We have received this crash report only from F-02H.
java.lang.IllegalArgumentException
Can not get supported output size under supported maximum for the format: 34
androidx.camera.camera2.internal.SupportedSurfaceCombination.getSupportedOutputSizes (SupportedSurfaceCombination.java:349)
androidx.camera.camera2.internal.SupportedSurfaceCombination.getSuggestedResolutions (SupportedSurfaceCombination.java:197)
androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions (Camera2DeviceSurfaceManager.java:198)
androidx.camera.core.CameraX.calculateSuggestedResolutions (CameraX.java:949)
androidx.camera.core.CameraX.bindToLifecycle (CameraX.java:351)
androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle (ProcessCameraProvider.java:230)
(our application's package name).CameraFragment.bindCameraUseCases (CameraFragment.java:174)
an...@google.com <an...@google.com> #8
Could you help to provide the following information to clarify the issue?
1. Is the full name of the device Fujitsu Arrows NX F-02H that has a 1440x2560 display?
2. Please help to provide the supported output sizes of ImageFormat.PRIVATE that is obtained by StreamConfigurationMap#getOutputSizes(int).
da...@gmail.com <da...@gmail.com> #9
- Is the full name of the device Fujitsu Arrows NX F-02H that has a 1440x2560 display?
Yes
- Please help to provide the supported output sizes of ImageFormat.PRIVATE that is obtained by StreamConfigurationMap#getOutputSizes(int).
Since we don't have this device, we'll try to collect this information in the next version of our app. The next version will be released later this month.
vi...@gmail.com <vi...@gmail.com> #10
Hello.
- Please help to provide the supported output sizes of ImageFormat.PRIVATE that is obtained by StreamConfigurationMap#getOutputSizes(int).
We have collected the output of the device where the crash occurs.
Device1
- Model : arrows Be F-05J
- Android Version : 7.1.1
- Supported output sizes of ImageFormat.PRIVATE
CameraId 0: 480x480
CameraId 1: 2048x1536 ,1920x1080 ,1280x720 ,960x720 ,640x480 ,320x240 ,176x144
Device2
- Model : Fujitsu arrows M04
- Android Version : 7.1.1
- Supported output sizes of ImageFormat.PRIVATE
CameraId 0: 480x480
CameraId 1: 2048x1536 ,1920x1080 ,1280x720 ,960x720 ,640x480 ,320x240 ,176x144
Additional Information
CameraX version : 1.0.0-beta04
We collect the supported output sizes by following code.
val errorString = buildString {
append("The supported output sizes of ImageFormat.PRIVATE: ")
(requireContext().getSystemService(Context.CAMERA_SERVICE) as CameraManager).apply {
cameraIdList.forEachIndexed { index, cameraId ->
val msg = if (VERSION.SDK_INT >= VERSION_CODES.M) {
val configurationMap =
getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
val sizes = configurationMap?.getOutputSizes(ImageFormat.PRIVATE)
"CameraId $index: ${sizes?.joinToString(" ,")}"
} else {
"CameraId $index: This device version is under M."
}
append(msg)
}
}
}
[Deleted User] <[Deleted User]> #11
an...@google.com <an...@google.com> #12
I tried to find the device specs and both 720x1280
size display. For the camera id 0 device, it is a different case that the display size is larger than 640x480
but the device only supports a 480x480
size. The case also caused the same IllegalArgumentException and was also fixed by 1.0.0-beta04
release. Before 480x480
size would be filtered out and then caused the IllegalArgumentException. After it was merged, the 640x480
size threshold was removed and then the 480x480
size would be kept and selected to use.
It looks like 1.0.0-beta04
release had been used to collect the supported sizes information. But the issue should have been fixed by 1.0.0-beta04
release. Did you only check the device model name to collect the supported sizes information or collect the information when the IllegalArgumentException issue happens again?
CameraX's 1.0.0-beta04
version. Maybe you can also consider to upgrade to the latest 1.0.0-rc01
version for your application. Thanks.
[Deleted User] <[Deleted User]> #13
Did you only check the device model name to collect the supported sizes information or collect the information when the IllegalArgumentException issue happens again?
We collect informations only from the device on which IllegalArgumentException happened.
Our latest app uses CameraX version 1.0.0-beta10
and this issue still occurres.
However we don't receive crash report from Fujitsu arrows Be F-05J
or Fujitsu arrows M04
so far. (This doesn't mean this issue is fixed on these devices because our app is heavily rely on camera so these device's user wouldn't use our app anymore.)
Instead, we receive crash report from
- Model : Fujitsu F-03K
- Android Version : 7.1.2
- Supported output sizes of ImageFormat.PRIVATE
CameraId 0 : 480x480
CameraId 1 : 2048x1536 ,1920x1080 ,1280x720 ,960x720 ,640x480 ,320x240 ,176x144
eu...@gmail.com <eu...@gmail.com> #14
I missed some settings when I simulated the issue by robolectric test so that I was not able to reproduce it. Now, I can reproduce the issue if the device only supports one 480x480 resolution. I'm working on the solution and target to make it included in next release.
da...@gmail.com <da...@gmail.com> #15
Branch: androidx-main
commit 69d15dff7bb857ee33a0f643ff42a0f8bc475ab2
Author: charcoalchen <charcoalchen@google.com>
Date: Fri Jan 08 18:30:03 2021
Fixed IllegalArgumentException issue happened when all preview supported sizes are smaller than 640x480 and display size is larger than 640x480.
Do not filter out sizes smaller than 640x480 when all preview supported sizes are smaller than 640x480 and display size is larger than 640x480.
Relnote:"Fixed IllegalArgumentException issue happened when all preview supported sizes are smaller than 640x480 and display size is larger than 640x480."
Bug: 150506192
Test: SupportedSurfaceCombinationTest
Change-Id: I2a63ce8e2ad42a9cc060c8635ac3603bf440b1ec
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
M camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
as...@gmail.com <as...@gmail.com> #16
an...@google.com <an...@google.com> #17
I think what happens is when you go to other screen your state still exist together with the ViewModel, then when you go back to the original screen lazyListingItems are recreated, and as Paging provides the values via a Flow there is no way to get the data synchronously, so there is always at least the first frame where lazyListingItems has 0 items yet, then LazyColumn is populated with 0 items so it has to reset the scroll position. It can't differentiate between the events where there are no items anymore and there are no items yet.
But if the LazyListState will be recreated as part of the recomposition then it can postpone the scroll position restoration till the first frame when there are at least 1 element in the list
ba...@gmail.com <ba...@gmail.com> #18
I have found a workaround that works for me.
The LazyPagingItems.kt
file was copied from the androidx.paging:paging-compose
artifact into my project (it doesn't have any other dependencies).
I modified it to add a flag inside the LazyPagingItems
class:
/**
* The number of items which can be accessed.
*/
val itemCount: Int get() = itemSnapshotList.size
// The code below was added:
/**
* Added to fix scroll state restoration - wait for this flag to be set to true
* before setting your [LazyListState] on the [LazyColumn].
*
* @author Baptiste Candellier
*/
var hasRestoredItems: Boolean = false
private set
The flag is set inside the updateItemSnapshotList()
method
private fun updateItemSnapshotList() {
itemSnapshotList = pagingDataDiffer.snapshot()
// The code below was added:
hasRestoredItems = true
}
Then on my composable, I wait for this flag to become true to pass the "real" LazyListState
, that comes from a ViewModel
.
LazyColumn(
// Wait for the items to be restored to set the real list state, so that it isn't reset in the meantime
state = if (lazyPagingItems.hasRestoredItems) lazyListState else LazyListState()
) {
// ... your items here
There might be edge cases but it works for me, I hope it helps.
im...@gmail.com <im...@gmail.com> #19
// Save and restore list state
fun lazyListSaver(): Saver<MutableState<LazyListState>, *> = listSaver(
save = { listOf(it.value.firstVisibleItemIndex, it.value.firstVisibleItemScrollOffset) },
restore = {
mutableStateOf(LazyListState(
firstVisibleItemIndex = it[0],
firstVisibleItemScrollOffset = it[1]
))
}
)
// Usage
fun ProfileTab(lazyListState: MutableState<LazyListState>)
LazyVerticalGrid(
state = lazyListState.value,
)
}
Hope this solution works.
an...@google.com <an...@google.com> #20
rememberLazyListState() is doing pretty much the same internally. Could you please elaborate a bit more on why the build in solution doesn't work for you?
im...@gmail.com <im...@gmail.com> #21
Ouch! I'm new on Compose, so don't know how state, rememberLazyListState() works so i directly pass
fun ProfileTab() LazyVerticalGrid( state = rememberLazyListState(), ) }
and while i switch tab from 1->2 and back from 2-> the state of LazyVerticalGrid regenerated, but i didn't try to save in state on globally and pass in composable.
After i seeing this
wh...@gmail.com <wh...@gmail.com> #22
as a lot of people mentioned, LazyColumn can't restore position correct when Paging has a Header
this is because rememberLazyListState can restore position when there are at least 1 element in the list
but if there is a Header or Footer in LazyColumn, then it will restore in first frame when paging's item count is still 0
so I store listState in ViewModel and restore it when Paging item count > 0
val listState = if (pagingData.itemCount > 0) viewModel.listState else rememberLazyListState()
ro...@gmail.com <ro...@gmail.com> #23
Try this workaround, you need to check lazyPagingItems before use:
@Composable
fun MainFrame(lazyPagingItems: LazyPagingItems<PerformanceEvent.Building>) {
val refresh = lazyPagingItems.loadState.refresh
// My temp solution
if (lazyPagingItems.itemCount == 0 && refresh is LoadState.NotLoading ) return //skip dummy state, waiting next compose
LazyColumn { ... }
}
ne...@gmail.com <ne...@gmail.com> #24
Here is a workaround:
@Composable
fun <T : Any> LazyPagingItems<T>.rememberLazyListState(): LazyListState {
// After recreation, LazyPagingItems first return 0 items, then the cached items.
// This behavior/issue is resetting the LazyListState scroll position.
// Below is a workaround. More info: https://issuetracker.google.com/issues/177245496.
return when (itemCount) {
// Return a different LazyListState instance.
0 -> remember(this) { LazyListState(0, 0) }
// Return rememberLazyListState (normal case).
else -> androidx.compose.foundation.lazy.rememberLazyListState()
}
}
Should we still expect a fix from any Jetpack library ?
ke...@gmail.com <ke...@gmail.com> #25
Could you provide a version name that contains the fix?
su...@gmail.com <su...@gmail.com> #26
Only thing that works is disabling phone rotation, or creating the pager flow before the NavHost. Are there any solutions?
wh...@gmail.com <wh...@gmail.com> #27
If your project does not have a deep dependency on the paging3 library, I recommend implementing a simple paging library yourself to avoid all the weird features of paging3. Paging library needs the coordination of the view layer and the model layer. It doesn't make sense to encapsulate these together.
Here's an example from my project. If you don't need to modify the list, it can be implemented much simpler.
da...@gmail.com <da...@gmail.com> #28
al...@mercari.com <al...@mercari.com> #29
Still not fixed in latest versions, workaround works. Please consider re-opening the issue.
co...@gmail.com <co...@gmail.com> #30
jo...@kalderstam.se <jo...@kalderstam.se> #31
Seconded. Still a problem in 1.3.1
[Deleted User] <[Deleted User]> #32
In our case, it seems to be triggered by adding headers/footers to the `LazyColumn`.
Please consider re-opening the issue.
il...@google.com <il...@google.com> #33
The default case (all of your items are loaded asynchronously) was fixed in cachedIn
in your layer above Compose (e.g., your ViewModel layer).
However, the case where you have some items available immediately (like a header and footer) and some items available only asynchronously, is not fixed. This is broken whether you use Paging or not - any data loaded from a Flow
would suffer this same problem (as they also would not be available in the first composition).
Creating an generic API for informing the Lazy Layout of when all asynchronously loaded items have finished loading (particularly noting that there can be multiple items
blocks loading from multiple asynchronous sources) is not something we can solve in the short or medium term.
That being said, we believe there may be a way to solve this in the specific case of headers+footers and a single call to collectAsLazyPagingItems
without having to wait for an overhaul of either the Paging or Lazy layout APIs, so we will be reopening this issue to track that internal investigation.
bi...@gmail.com <bi...@gmail.com> #34
pa...@outlook.com <pa...@outlook.com> #35
Sounds like Paging and Component are being developed with a lot of various serious issues that are piling with each version, and the team does not have any intention of fixing them. That's alright, at least now we can finally stop waiting for this to be fixed and instead stop using them entirely. Good luck with this.
cl...@google.com <cl...@google.com> #36
Compose requires an initial state for valid first composition.
Paging 3's entire architecture is based around emitting data through a Flow that doesn't emit until collected.
Therefore, significant changes within Paging 3 are required to enable initial states in paging-compose without collection. While these changes are not easily resolvable, we hope to address them in the coming year.
au...@gmail.com <au...@gmail.com> #37
vi...@gmail.com <vi...@gmail.com> #39
ty...@gmail.com <ty...@gmail.com> #40
ap...@google.com <ap...@google.com> #41
Branch: androidx-main
commit 4a567a83c33a3f15556d4777e97327e418cbe42e
Author: Clara Fok <clarafok@google.com>
Date: Wed Apr 26 12:29:43 2023
Initialize PagingDataDiffer with cached data
PagingDataDiffer constructor now accepts a nullable PagingData containing a nullable cached PageEvent.Insert. PagePresenter and combinedLoadStatesCollection will be initialized wiht the cached data if present. This allows cached items and loadStates to be accessible immediately without requiring any collection.
Note that HintReciver and UiReceiver is not set, hence differ will not respond to any UI input (scrolling / refresh etc) until a real PagingData has been collected from.
Test: ./gradlew paging:paging-common:test
Bug: 177245496
Change-Id: I3a9a80486a1e345699745311dcb585efbf7939bd
M paging/paging-common/src/main/kotlin/androidx/paging/PagePresenter.kt
M paging/paging-common/src/main/kotlin/androidx/paging/PagingDataDiffer.kt
M paging/paging-common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
ap...@google.com <ap...@google.com> #42
Branch: androidx-main
commit ac2a48843976a46cdf9eb6db1d4d08d59deecbd8
Author: Clara Fok <clarafok@google.com>
Date: Tue Apr 25 16:43:38 2023
Exposed cached data via PagingData
When using Flow<PagingData<T>>.cachedIn(scope), data that has been collected within that generation is cached for as long as the scope remains alive.
Normally the cachedData can only be accessed by new subscriptions when they collect on the SharedFlow returned by cachedIn. Now we expose this cachedData via PagingData so that the cached data can be accessed synchronously without requiring collection.
Test: ./gradlew paging:paging-common:test
Bug: 177245496
Change-Id: I36a894d7d90f61396604e7847c5be6027b5e0991
M paging/paging-common/src/main/kotlin/androidx/paging/CachedPageEventFlow.kt
M paging/paging-common/src/main/kotlin/androidx/paging/CachedPagingData.kt
M paging/paging-common/src/main/kotlin/androidx/paging/PagingData.kt
M paging/paging-common/src/test/kotlin/androidx/paging/CachingTest.kt
8h...@gmail.com <8h...@gmail.com> #43
ap...@google.com <ap...@google.com> #44
Branch: androidx-main
commit 75b22ef9f04fc4d615b75f65d904dd4cc765bffd
Author: Clara Fok <clarafok@google.com>
Date: Thu Apr 27 14:03:07 2023
Cached data immediately available in LazyPagingItems
Paged data can be cached via pager.flow.cachedIn(scope). If collecting LazyPagingItems from this cachedIn flow, any cached data will be made available for presentation upon #collectAsLazyPagingItems initialization without requiring asynchronous collection.
This means that upon configuration change or navigating away and back, instead of LazyPagingItems containing zero items, it will now contain previously loaded data that can be immediately presented within initial composition. This helps preserve scroll state and a smoother UI transition.
Note that this only applies to flows returned directly from pager.flow.cachedIn(scope), so mapping or transformations should be applied prior to cachedIn.
Test: ./gradlew paging:paging-compose:cC
Fixes: 177245496
Relnote: "Cached data from pager.flow.cachedIn that has been collected in LazyPagingItems will now be immediately available after state restoration without requiring asyncrhonous collection. This means the cached data will be ready for presentation immediately upon initial composition after state is restored."
Change-Id: I97a6078c0563f8017af24448c32e59b86a987465
M paging/paging-compose/src/androidTest/java/androidx/paging/compose/LazyPagingItemsTest.kt
M paging/paging-compose/src/main/java/androidx/paging/compose/LazyPagingItems.kt
cl...@google.com <cl...@google.com> #45
This has been fixed internally and will be available in the next release. The next release version is TBD.
In short, the fix works by making cached data immediately available for presentation after config change / navigation. This prevents the list from having zero items right after config change/ navigation so the scroll state will be preserved without requiring workarounds such as
That said, it only works if there is cached data to begin with. This means you need pager.flow.cachedIn(scope)
. Note that any PagedData mapping/transformations should be applied prior to cachedIn(), such as
val pager = pager.flow.map { pagingData ->
pagingData.map {
// map items
}
}.cachedIn(scope)
8h...@gmail.com <8h...@gmail.com> #46
Is it going to fix incorrect loadState
(Loading
) as well (to avoid displaying incorrect refresh indicator to users)?
val lazyPagingItems = viewModel.pagingDataExample.collectAsLazyPagingItems()
val loadState = lazyPagingItems.loadState.refresh // loadState == Loading initially on config changes/navigation
It should be NotLoading
if data is returned from cahce and no request to refresh is triggered
cl...@google.com <cl...@google.com> #47
Yes it will start with NotLoading
if displaying cachedData.
na...@google.com <na...@google.com> #48
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.paging:paging-common:3.2.0-alpha05
il...@google.com <il...@google.com> #49
I'll note that while some of the changes from this bug made it into
ju...@google.com <ju...@google.com> #50
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.paging:paging-compose:1.0.0-alpha20
so...@gmail.com <so...@gmail.com> #51
cl...@google.com <cl...@google.com> #52
paging-common 3.2.0-alpha06
?
il...@google.com <il...@google.com> #53
Re
so...@gmail.com <so...@gmail.com> #54
is...@gmail.com <is...@gmail.com> #55
Regarding the workaround from firstVisibleItemIndex
and firstVisibleItemScrollOffset
to continue to remain the same in case other code depends on them, it looks like the workaround should be modified to this?
@Composable
fun <T : Any> LazyPagingItems<T>.rememberLazyGridState(): LazyGridState {
val state = androidx.compose.foundation.lazy.grid.rememberLazyGridState()
return when (itemCount) {
// Return a different LazyListState instance.
0 -> remember(this) {
LazyGridState(
firstVisibleItemIndex = state.firstVisibleItemIndex,
firstVisibleItemScrollOffset = state.firstVisibleItemScrollOffset
)
}
// Return rememberLazyListState (normal case).
else -> state
}
}
h9...@gmail.com <h9...@gmail.com> #56
If there is a combined flow, cachedIn does not seem to work. Could you please confirm?
val pager = pager.flow
.map { pagingData ->
pagingData.map {
// map items
}
}
.cachedIn(scope)
.combine(otherFlow) { pagingData, otherFlow ->
pagingData.map{
// something
}
}
.cachedIn(scope)
If you call the pager again with collectAsLazyPagingItems()
, LoadState will be called LoadState.Loading
rather than LoadState.NotLoading
.
cl...@google.com <cl...@google.com> #57
Re
jo...@mozilla.com <jo...@mozilla.com> #58
The workarounds, like in
il...@google.com <il...@google.com> #59
Re
Please file a new issue with a sample project that reproduces your issue if you are seeing something different.
pa...@gmail.com <pa...@gmail.com> #60
im having a similar problem as
cl...@google.com <cl...@google.com> #61
Re
pr...@gmail.com <pr...@gmail.com> #62
@Composable
fun <T : Any> LazyPagingItems<T>.rememberLazyListState(): LazyListState {
val state = androidx.compose.foundation.lazy.rememberLazyListState()
val scrollIndex = rememberSaveable { mutableIntStateOf(0) }
val coroutineScope = rememberCoroutineScope()
// After recreation, LazyPagingItems first return 0 items, then the cached items.
// This behavior/issue is resetting the LazyListState scroll position.
return when (itemCount) {
// Return a different LazyListState instance.
0 -> rememberSaveable(saver = LazyListState.Saver) {
scrollIndex.intValue = state.firstVisibleItemIndex
LazyListState(state.firstVisibleItemIndex, state.firstVisibleItemScrollOffset)
}
else -> {
if(scrollIndex.intValue in 1..<itemCount) {
// Return state after scrolling.
LaunchedEffect("") {
coroutineScope.launch {
state.animateScrollToItem(scrollIndex.intValue, state.firstVisibleItemScrollOffset)
scrollIndex.intValue = 0
}
}
}
state
}
}
}
se...@gmail.com <se...@gmail.com> #63
I want to share my case with a positive result.
I use compose paging 3 (api + room), navigation.
This is my case in detail.
1. Screen A (list with api + room pagination)
2. Screen B (details + changing data in the database by item ID)
When I changed the data on screen B and returned to screen A, the position was reset.
The reason was as follows. When my LazyPagerItems<*> object was with ItemCount == 0, I used item {} to show placeholder. That was the reason! When I started using items even with ItemCount == 0, the position reset stopped happening.
Bad Case:
Lazy Column() {
when {
values == null || values.itemCount == 0 -> item {} //simple item
items () {} //for paging items
}
}
Nice Case:
Lazy Column() {
when {
values == null -> item {} //simple item
items (
count = values.itemCount,
) {} //for paging items
}
}
Then I started adding elements to LazyColumn and making it combined. In this case, it also reset the position! By removing the item at the beginning, the list began to work correctly.
Bad Case:
Lazy Column() {
item {} //simple item
item {} //simple item
items () {} //for paging items
}
Nice Case:
Lazy Column() {
items () {} //for paging items
}
to...@gmail.com <to...@gmail.com> #64
Yes they do not want the if and placeholders to be inside the LazyColumn we are supposed to use if outside of the LazyColum.
The workaround is to use a fake lazystate until your data is loaded.
See for example solution
cl...@google.com <cl...@google.com> #65
re cachedIn()
, you shouldn't need a workaround. Can you upload a sample app for me to take a look?
to...@gmail.com <to...@gmail.com> #66
Cachein does not keep the data when the app is killed in the background or viewmodel is unloaded.
sa...@gmail.com <sa...@gmail.com> #67
to...@gmail.com <to...@gmail.com> #68
That's cute but you might actually want to read the issue.
hu...@nevix.tech <hu...@nevix.tech> #69
val pager = pager.flow
.map { pagingData ->
pagingData.map {
// map items
}
}
.cachedIn(scope)
.combine(otherFlow) { pagingData, otherFlow ->
pagingData.map{
// something
}
}
.cachedIn(scope)
my-version = androidx.paging:paging-compose:3.3.5
When otherFlow updates data, an error occurs: Attempt to collect twice from pageEventFlow, which is an illegal operation. Did you forget to call Flow<PagingData<*>>.cachedIn(coroutineScope)?
Description
Jetpack Compose release version: 1.0.0-alpha09 Android Studio Build: Build #AI-202.7319.50.2031.7049475, built on December 24, 2020
Steps to Reproduce:
NavHost
-ed composable screen containing aLazyColumn
built withLazyPagingItems
collected from a view modelResult: the LazyColumn is scrolled back to top
Expected: the scroll position should be remembered
Sample code that works:https://gist.github.com/CyrilFind/5c7d108dd8d030fe7a6a556e43f29f6f
If the
.collectAsLazyPagingItems()
line from this sample is done before declaring theNavHost
, it works as expected but if it is done inside thecomposable
block, it does not.