Fixed
Status Update
Comments
[Deleted User] <[Deleted User]> #2
Or when changing to textView.textMetricsParamsCompat still crash.
private fun setAsyncText(textView: AppCompatTextView, text: String?) {
if (!text.isNullOrEmpty()) {
val textFuture = PrecomputedTextCompat.getTextFuture(text!!, textView.textMetricsParamsCompat, null)
textView.setTextFuture(textFuture) //Crash
}
}
private fun setAsyncText(textView: AppCompatTextView, text: String?) {
if (!text.isNullOrEmpty()) {
val textFuture = PrecomputedTextCompat.getTextFuture(text!!, textView.textMetricsParamsCompat, null)
textView.setTextFuture(textFuture) //Crash
}
}
[Deleted User] <[Deleted User]> #3
add this line :
textView.setLayoutDirection(ViewCompat.getLayoutDirection(textView));
before :
setTextFuture(....)
textView.setLayoutDirection(ViewCompat.getLayoutDirection(textView));
before :
setTextFuture(....)
jg...@google.com <jg...@google.com>
[Deleted User] <[Deleted User]> #4
Thanks, #3. It worked.
But I think it is better when set before this line
val textFuture = PrecomputedTextCompat.getTextFuture(text!!, textView.textMetricsParamsCompat, null)
Set android:layoutDirection="locale" or android:layoutDirection="inherit" for AppCompatTextView in the XML layout didn't this problem.
The new method btw re-set layoutDirector. Weird! This should handle in the AppcompatTextView.
private fun setAsyncText(textView: AppCompatTextView, text: String?) {
if (!text.isNullOrEmpty()) {
textView.layoutDirection = textView.layoutDirection
val textFuture = PrecomputedTextCompat.getTextFuture(text!!, textView.textMetricsParamsCompat, null)
textView.setTextFuture(textFuture) //Crash
}
}
But I think it is better when set before this line
val textFuture = PrecomputedTextCompat.getTextFuture(text!!, textView.textMetricsParamsCompat, null)
Set android:layoutDirection="locale" or android:layoutDirection="inherit" for AppCompatTextView in the XML layout didn't this problem.
The new method btw re-set layoutDirector. Weird! This should handle in the AppcompatTextView.
private fun setAsyncText(textView: AppCompatTextView, text: String?) {
if (!text.isNullOrEmpty()) {
textView.layoutDirection = textView.layoutDirection
val textFuture = PrecomputedTextCompat.getTextFuture(text!!, textView.textMetricsParamsCompat, null)
textView.setTextFuture(textFuture) //Crash
}
}
jg...@google.com <jg...@google.com> #5
Sorry. I forgot the info.
minSdk 21
targetSdk 28
Thanks #3 again.
minSdk 21
targetSdk 28
Thanks #3 again.
jg...@google.com <jg...@google.com> #6
App Crash at
TextViewCompat.java:889
if (!param.equals(precomputed.getParams())) {
throw new IllegalArgumentException("Given text can not be applied to TextView.");
}
PrecomputedTextCompat.class:334
with : this.mTextDir != other.getTextDirection() == true
So,
TextDirection on TextView and TextDirection on Param is difference
maybe, it handled wrong or missing conditional on getTextDirectionHeuristic of TextViewCompat
TextViewCompat.java:889
if (!param.equals(precomputed.getParams())) {
throw new IllegalArgumentException("Given text can not be applied to TextView.");
}
PrecomputedTextCompat.class:334
with : this.mTextDir != other.getTextDirection() == true
So,
TextDirection on TextView and TextDirection on Param is difference
maybe, it handled wrong or missing conditional on getTextDirectionHeuristic of TextViewCompat
jg...@google.com <jg...@google.com> #7
With reference to comment #4 , issue is resolved by implementing suggested changes in comment #3 . Can you please confirm if we need to still investigate this issue ?
jg...@google.com <jg...@google.com> #8
Yes. textView.layoutDirection = textView.layoutDirection(>= API17) or ViewCompat.setLayoutDirection(textView, ViewCompat.getLayoutDirection(textView)) will resolve this bug.
But I think you should handle it in the AppcompatTextView. It is better. If a developer forgets testing with RTL. I think this is the nightmare(it is difficult to determine the bug) when they update their app on the Play Store.
I read this article, in the part databing he noted about set the direction
https://medium.com/google-developers/prefetch-text-layout-in-recyclerview-4acf9103f438 '
fun asyncText
..........
// first, set all measurement affecting properties of the text
// (size, locale, typeface, direction, etc)
But in the offical document isn't good (lack direction)
https://developer.android.com/reference/androidx/appcompat/widget/AppCompatTextView.html#setTextFuture(java.util.concurrent.Future%3Candroidx.core.text.PrecomputedTextCompat%3E)
Anything layout related property changes, text size, typeface, letter spacing, etc after this method call will causes IllegalArgumentException during View measurement.
My view: Handling this in the AppcompatTextView is the best choice if you can do it.
Thanks!
But I think you should handle it in the AppcompatTextView. It is better. If a developer forgets testing with RTL. I think this is the nightmare(it is difficult to determine the bug) when they update their app on the Play Store.
I read this article, in the part databing he noted about set the direction
fun asyncText
..........
// first, set all measurement affecting properties of the text
// (size, locale, typeface, direction, etc)
But in the offical document isn't good (lack direction)
Anything layout related property changes, text size, typeface, letter spacing, etc after this method call will causes IllegalArgumentException during View measurement.
My view: Handling this in the AppcompatTextView is the best choice if you can do it.
Thanks!
[Deleted User] <[Deleted User]> #9
I think should handle setLayoutDirection in the AppcompatTextView when setTextFuture, it will simpler for dev when implement TextFuture.
[Deleted User] <[Deleted User]> #10
We have passed this to the development team and will update this issue with more information as it becomes available.
jg...@google.com <jg...@google.com> #11
Fix released with appCompat 1.0.2, core 1.0.1
[Deleted User] <[Deleted User]> #12
Similar request has been raised in another bug in Android AOSP external tracker in b/123131632 .
Description shared by an external reporter:
================================
1.
Version used: androidx.appcompat:appcompat:1.1.0-alpha1
AppCompatTextView.setTextFuture
http://crashes.to/s/a9335204277
i foundhttps://issuetracker.google.com/issues/113070424 say version 1.0.2 fixed, But it still exists。
2.
Non-fatal Exception: java.lang.IllegalArgumentException: Given text can not be applied to TextView.
at androidx.core.widget.TextViewCompat.retrieveField(Unknown Source:22)
at androidx.appcompat.widget.AppCompatTextView.consumeTextFutureAndSetBlocking(Unknown Source:15)
at androidx.appcompat.widget.AppCompatTextView.onMeasure(Unknown Source)
at com.bilibili.magicasakura.widgets.AppCompatTintTextView.onMeasure(Unknown Source)
at android.view.View.measure(View.java:22145)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
at android.view.View.measure(View.java:22145)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at androidx.cardview.widget.CardView.onMeasure(Unknown Source:80)
at android.view.View.measure(View.java:22145)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(Unknown Source:98)
at androidx.recyclerview.widget.LinearLayoutManager.generateDefaultLayoutParams(Unknown Source:60)
at androidx.recyclerview.widget.LinearLayoutManager.generateDefaultLayoutParams(Unknown Source:44)
at androidx.recyclerview.widget.LinearLayoutManager.findViewByPosition(Unknown Source:36)
at androidx.recyclerview.widget.LinearLayoutManager.setOrientation(Unknown Source:6)
at androidx.recyclerview.widget.RecyclerView.exceptionLabel(Unknown Source:39)
at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(Unknown Source:91)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:979)
at android.view.Choreographer.doCallbacks(Choreographer.java:791)
at android.view.Choreographer.doFrame(Choreographer.java:723)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:965)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6707)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:108)
device: meizu, Android 7 and 8
And you can see fabric detailhttp://crashes.to/s/a9335204277
===========================================
Requesting team for initial inputs. Please let us know if this can be handled as a part of this bug else we will create a separate bug for this.
Description shared by an external reporter:
================================
1.
Version used: androidx.appcompat:appcompat:1.1.0-alpha1
AppCompatTextView.setTextFuture
i found
2.
Non-fatal Exception: java.lang.IllegalArgumentException: Given text can not be applied to TextView.
at androidx.core.widget.TextViewCompat.retrieveField(Unknown Source:22)
at androidx.appcompat.widget.AppCompatTextView.consumeTextFutureAndSetBlocking(Unknown Source:15)
at androidx.appcompat.widget.AppCompatTextView.onMeasure(Unknown Source)
at com.bilibili.magicasakura.widgets.AppCompatTintTextView.onMeasure(Unknown Source)
at android.view.View.measure(View.java:22145)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
at android.view.View.measure(View.java:22145)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
at androidx.cardview.widget.CardView.onMeasure(Unknown Source:80)
at android.view.View.measure(View.java:22145)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(Unknown Source:98)
at androidx.recyclerview.widget.LinearLayoutManager.generateDefaultLayoutParams(Unknown Source:60)
at androidx.recyclerview.widget.LinearLayoutManager.generateDefaultLayoutParams(Unknown Source:44)
at androidx.recyclerview.widget.LinearLayoutManager.findViewByPosition(Unknown Source:36)
at androidx.recyclerview.widget.LinearLayoutManager.setOrientation(Unknown Source:6)
at androidx.recyclerview.widget.RecyclerView.exceptionLabel(Unknown Source:39)
at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(Unknown Source:91)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:979)
at android.view.Choreographer.doCallbacks(Choreographer.java:791)
at android.view.Choreographer.doFrame(Choreographer.java:723)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:965)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6707)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:886)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:108)
device: meizu, Android 7 and 8
And you can see fabric detail
===========================================
Requesting team for initial inputs. Please let us know if this can be handled as a part of this bug else we will create a separate bug for this.
jg...@google.com <jg...@google.com>
jg...@google.com <jg...@google.com> #13
Please ignore comment #12 .
[Deleted User] <[Deleted User]> #14
Thanks for the suggestion above, creating a new Fragment every time definitely fixes the problem albeit some very ugly code implementation and hacks I had to write to do some state saving in my code (since ViewModels are attached to a specific Fragment instance), my subsequent fragments also need to do some ugly state saving (playing media).
Looking forward to erasing all of this ugly code on next update!
Looking forward to erasing all of this ugly code on next update!
[Deleted User] <[Deleted User]> #15
For anybody who has the same exact problem, page state saving works for me in the following manner:
binding.gamePagerRoot.apply {
// Set the Adapter for our Fragment
adapter = gamePagerAdapter
// Do not allow user touch for this ViewPager2 to affect its scroll, should only be scrolled programmatically
isUserInputEnabled = false
// Set the Page Transformation
setPageTransformer(genStackedPageTransformer2())
// Listen to page change calbacks
registerOnPageChangeCallback(onPageChangeCallback)
// Customize the RecyclerView child
val recyclerView = getChildAt(0) as RecyclerView
// Remove the overscroll shaddow
recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
// Allow nested scrolling
recyclerView.isNestedScrollingEnabled = true
// If we are on a different page as specified by our ViewModel, make sure to scroll to the page instantly (no animation)
if(gamePagerVM?.gamePageIds?.size ?: 1 > 1) {
recyclerView.viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener{
override fun onGlobalLayout() {
if(recyclerView.childCount >= gamePagerVM?.currPage ?: 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
// If the current page is not 0, set the current page
setCurrentItem(gamePagerVM?.currPage ?: 0, false)
}
}
})
}
}
binding.gamePagerRoot.apply {
// Set the Adapter for our Fragment
adapter = gamePagerAdapter
// Do not allow user touch for this ViewPager2 to affect its scroll, should only be scrolled programmatically
isUserInputEnabled = false
// Set the Page Transformation
setPageTransformer(genStackedPageTransformer2())
// Listen to page change calbacks
registerOnPageChangeCallback(onPageChangeCallback)
// Customize the RecyclerView child
val recyclerView = getChildAt(0) as RecyclerView
// Remove the overscroll shaddow
recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
// Allow nested scrolling
recyclerView.isNestedScrollingEnabled = true
// If we are on a different page as specified by our ViewModel, make sure to scroll to the page instantly (no animation)
if(gamePagerVM?.gamePageIds?.size ?: 1 > 1) {
recyclerView.viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener{
override fun onGlobalLayout() {
if(recyclerView.childCount >= gamePagerVM?.currPage ?: 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
// If the current page is not 0, set the current page
setCurrentItem(gamePagerVM?.currPage ?: 0, false)
}
}
})
}
}
ap...@google.com <ap...@google.com> #16
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 7166ba571d594baa9016e02c3b5fe967da0b8ec0
Author: Jakub Gielzak <jgielzak@google.com>
Date: Tue Aug 27 16:20:54 2019
Fix for FragmentStateAdapter#gcFragments()
Fix for an issue with FragmentStateAdapter garbage collection mechanism.
The bug manifested itself in the following scenario:
- ViewPager2 host Fragment view recreated 3+ times in a window < 10s,
- Host Fragment instances added to the back stack,
- ViewPager2 adapter set to null in onViewDestoyed (too late as view
state already saved, but affecting PageFragment book-keeping).
The fix adds another criteria to gcFragments() in case a
PageFragment instance gets taken over by a later created instance of
FragmentStateAdapter.
Bug: 139095195
Test: ./gradlew viewpager2:connectedCheck
Change-Id: If42bc4e65e8fe52cc0dcd9bbf67a0c55d3c535b1
A viewpager2/src/androidTest/java/androidx/viewpager2/widget/HostFragmentBackStackTest.kt
M viewpager2/src/main/java/androidx/viewpager2/adapter/FragmentStateAdapter.java
https://android-review.googlesource.com/1108545
https://goto.google.com/android-sha1/7166ba571d594baa9016e02c3b5fe967da0b8ec0
Branch: androidx-master-dev
commit 7166ba571d594baa9016e02c3b5fe967da0b8ec0
Author: Jakub Gielzak <jgielzak@google.com>
Date: Tue Aug 27 16:20:54 2019
Fix for FragmentStateAdapter#gcFragments()
Fix for an issue with FragmentStateAdapter garbage collection mechanism.
The bug manifested itself in the following scenario:
- ViewPager2 host Fragment view recreated 3+ times in a window < 10s,
- Host Fragment instances added to the back stack,
- ViewPager2 adapter set to null in onViewDestoyed (too late as view
state already saved, but affecting PageFragment book-keeping).
The fix adds another criteria to gcFragments() in case a
PageFragment instance gets taken over by a later created instance of
FragmentStateAdapter.
Bug: 139095195
Test: ./gradlew viewpager2:connectedCheck
Change-Id: If42bc4e65e8fe52cc0dcd9bbf67a0c55d3c535b1
A viewpager2/src/androidTest/java/androidx/viewpager2/widget/HostFragmentBackStackTest.kt
M viewpager2/src/main/java/androidx/viewpager2/adapter/FragmentStateAdapter.java
ap...@google.com <ap...@google.com> #17
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 39daf73f75d04b1ba52b007781355595430f8dab
Author: Jakub Gielzak <jgielzak@google.com>
Date: Tue Aug 27 16:20:16 2019
Made test FragmentAdapter more flexible.
Needed for the next CL.
Bug: 139095195
Test: ./gradlew viewpager2:connectedCheck
Change-Id: I3aa4b8a131d3d7bca248f94641c5ee643c6f1819
M viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
M viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapter.kt
https://android-review.googlesource.com/1108544
https://goto.google.com/android-sha1/39daf73f75d04b1ba52b007781355595430f8dab
Branch: androidx-master-dev
commit 39daf73f75d04b1ba52b007781355595430f8dab
Author: Jakub Gielzak <jgielzak@google.com>
Date: Tue Aug 27 16:20:16 2019
Made test FragmentAdapter more flexible.
Needed for the next CL.
Bug: 139095195
Test: ./gradlew viewpager2:connectedCheck
Change-Id: I3aa4b8a131d3d7bca248f94641c5ee643c6f1819
M viewpager2/src/androidTest/java/androidx/viewpager2/widget/BaseTest.kt
M viewpager2/src/androidTest/java/androidx/viewpager2/widget/swipe/FragmentAdapter.kt
jg...@google.com <jg...@google.com> #18
beta04 with a fix for this was released today
Description
Creating Sample app to verify, but in case this is already a known issue