-
Notifications
You must be signed in to change notification settings - Fork 731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Safe epoxy char sequence #4837
Safe epoxy char sequence #4837
Changes from all commits
d7c9e15
ca44d8f
27161bf
a38f5f9
4642299
e03c806
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Stop using CharSequence as EpoxyAttribute because it can lead to crash if the CharSequence mutates during rendering. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright (c) 2022 New Vector Ltd | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package im.vector.app.core.epoxy.charsequence | ||
|
||
/** | ||
* Wrapper for a CharSequence, which support mutation of the CharSequence, which can happen during rendering | ||
*/ | ||
class EpoxyCharSequence(val charSequence: CharSequence) { | ||
private val hash = charSequence.toString().hashCode() | ||
|
||
override fun hashCode() = hash | ||
override fun equals(other: Any?) = other is EpoxyCharSequence && other.hash == hash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do not compare the String content, since the risk of collision is low enough, and Epoxy is mainly using hashCode() to compare items |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (c) 2021 New Vector Ltd | ||
* Copyright (c) 2022 New Vector Ltd | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Happy new year! |
||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
|
@@ -14,8 +14,9 @@ | |
* limitations under the License. | ||
*/ | ||
|
||
package im.vector.app.core.epoxy.util | ||
package im.vector.app.core.epoxy.charsequence | ||
|
||
import android.text.SpannableString | ||
|
||
fun CharSequence?.preventMutation(): CharSequence? = this?.let { SpannableString(it) } | ||
/** | ||
* Extensions to wrap CharSequence to EpoxyCharSequence | ||
*/ | ||
fun CharSequence.toEpoxyCharSequence() = EpoxyCharSequence(this) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,7 @@ import im.vector.app.core.extensions.setAttributeTintedImageResource | |
abstract class RadioButtonItem : VectorEpoxyModel<RadioButtonItem.Holder>() { | ||
|
||
@EpoxyAttribute | ||
var title: CharSequence? = null | ||
var title: String? = null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whenever a CharSequence is not required, it simpler to use an immutable String |
||
|
||
@StringRes | ||
@EpoxyAttribute | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let the EpoxyCharSequence inherits CharSequence like this, to avoid accessing charSequence value everywhere
class EpoxyCharSequence(val charSequence: CharSequence) : CharSequence by charSequence
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, let me try it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not work, the TextView displays the Object and not the CharSequence... Weird
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to @ganfra investigation, it can work using
but I prefer not to create a new SpannableString for each charSequence.
Using
.charSequence
whenever it is necesssary is probably better, because it forces the developer to do it (no "hidden magic")