ReadMoreTextView icon indicating copy to clipboard operation
ReadMoreTextView copied to clipboard

Getting crash due to StringIndexOutOfBoundsException inside RecyclerView

Open kasim1011 opened this issue 4 years ago • 10 comments

I'm using ReadMoreTextView in RecyclerView. Getting crash due to StringIndexOutOfBoundsException so many times inside RecyclerView.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.waspito, PID: 17585
    java.lang.StringIndexOutOfBoundsException: length=35; index=241
        at java.lang.String.getChars(String.java:788)
        at android.text.TextUtils.getChars(TextUtils.java:148)
        at android.text.SpannableStringBuilder.<init>(SpannableStringBuilder.java:68)
        at com.borjabravo.readmoretextview.ReadMoreTextView.updateCollapsedText(ReadMoreTextView.java:137)
        at com.borjabravo.readmoretextview.ReadMoreTextView.getTrimmedText(ReadMoreTextView.java:114)
        at com.borjabravo.readmoretextview.ReadMoreTextView.getDisplayableText(ReadMoreTextView.java:90)
        at com.borjabravo.readmoretextview.ReadMoreTextView.setText(ReadMoreTextView.java:84)
        at com.borjabravo.readmoretextview.ReadMoreTextView.access$200(ReadMoreTextView.java:33)
        at com.borjabravo.readmoretextview.ReadMoreTextView$1.onGlobalLayout(ReadMoreTextView.java:206)
        at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:1056)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2629)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1722)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7605)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1029)
        at android.view.Choreographer.doCallbacks(Choreographer.java:852)
        at android.view.Choreographer.doFrame(Choreographer.java:787)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1014)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7397)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)

kasim1011 avatar May 28 '20 06:05 kasim1011

same

eggham0518 avatar Jun 24 '20 05:06 eggham0518

I think not only in recyclerview

Narinc avatar Sep 23 '20 22:09 Narinc

have solve it ?

Qdafengzi avatar Oct 26 '20 05:10 Qdafengzi

hmm i think need. to change to other lib

fukemy avatar Mar 25 '21 08:03 fukemy

I've tried debugging this and I found that this part right here is causing it.

On this method of ReadMoreTextView.java

private CharSequence updateCollapsedText() {
        int trimEndIndex = text.length();
        switch (trimMode) {
            case TRIM_MODE_LINES:
                trimEndIndex = lineEndIndex - (ELLIPSIZE.length() + trimCollapsedText.length() + 1);
                if (trimEndIndex < 0) {
                    trimEndIndex = trimLength + 1;
                }
                break;
            case TRIM_MODE_LENGTH:
                trimEndIndex = trimLength + 1;
                break;
        }
        SpannableStringBuilder s = new SpannableStringBuilder(text, 0, trimEndIndex)
                .append(ELLIPSIZE)
                .append(trimCollapsedText);
        return addClickableSpan(s, trimCollapsedText);
    }

When you set the mode to TRIM_MODE_LINES, that case will execute and there are times that the value of trimEndIndex is negative so the if statement below it will execute and when trimLength is greater than the actual text length, this will cause the SpannableStringBuilder to throw and index out of bounds error.

ps. the trimLength have a default value of 240

ShareemGelitoTeofilo avatar Jun 18 '21 13:06 ShareemGelitoTeofilo

I found out that one of the reasons for this is old data is still there, because of the recycling mechanism of recyclerview. What I mean is the old text is still there and it was used to calculate other variables within the ReadMoreTextView to initialize it, so by the time that the new text is passed into it will used the precomputed values from the old data. In this case the length of the old text is used to initialize the SpannableStringBuilder which caused the index out of bounds.

I added a setting to recyclerview to disable the recycling mechanism to avoid this issue. Altho it solved it, but it beats the purpose of the recyclerview and it obviously affected the performance. Have to find another way for this. Maybe put a handler inside the ReadMoreTextView to update the data effectively or wait for the recyclerview to finally load the new data first, but don't know how yet. Hope this will help others to figure out this problem once and for all.

ShareemGelitoTeofilo avatar Jun 19 '21 06:06 ShareemGelitoTeofilo

i do not have much time to solve the library problem, so i using this lib : https://github.com/devendroid/ReadMoreOption

fukemy avatar Jun 19 '21 06:06 fukemy

I have a possible solution. I'll work on this.

ShareemGelitoTeofilo avatar Jun 19 '21 18:06 ShareemGelitoTeofilo

ok buddy, if u want to make it easy i think it will better using this layout and toggle hide/show instead of readmore

LinearLayout vertical LinearLayout horizontal [TRIM_TEXT] -Read more btn- LinearLayout horizontal [FULL_TEXT] LinearLayout vertical

fukemy avatar Jun 19 '21 22:06 fukemy

Is anyone still working on this lib? No pull requests, no commits, is there maybe an updated repo with this issues fixed?

baltekgajda avatar Sep 06 '21 10:09 baltekgajda