Skip to content

Used in ViewPager fragments randomly crashes the app (NullPointerException: Attempt to invoke virtual method void View.sendAccessibilityEventUnchecked) #6

@Jars-of-jam-Scheduler

Description

@Jars-of-jam-Scheduler

Hello,

I am using your library in a project. I am facing an issue that makes the app randomly crash when your library is used within a fragment within a ViewPager. I have isolated the part of the library that leads to the bug. Full minimal and executable sources and more informations are available in this StackOverflow question: https://stackoverflow.com/questions/61061130/textview-in-viewpager-fragments-randomly-crashes-the-app-nullpointerexception-a .

Could you please take a look at this?

I thank you in advance,
Best regards,


Edit

I think I've found a solution: using runOnUiThread in the following class (changes were added, you can compare it to your own class, I didn't want to fork/do a pull request just for that .......... also, you can find a bit more info in my Stackoverlow Question, which I linked above):

package libs.AutoScrollTextView;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatTextView;

import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 跑马灯效果TextView
 *
 * @author haohao on 2017/9/21 下午 02:33
 * @version v1.0
 */
public class MarqueeTextView extends AppCompatTextView {

    private int currentScrollPos = 0;
    //速度
    private int speed = 6;
    // 文字宽度
    private int textWidth = -1;
    //是否计算了宽度
    private volatile boolean isMeasured = false;
    //是否完成移动
    private volatile boolean flag = false;
    //是否停止移动
    private volatile boolean isStop = false;

    private IMarqueeListener marqueeListener;
    private Future future;

    ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);

    final TimerTask task = new TimerTask() {
        @Override
        public void run() {
            ((AppCompatActivity) getContext()).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (textWidth == -1) {
                        postInvalidate();
                        return;
                    }
                    if (isStop) {
                        return;
                    }
                    if (!flag && currentScrollPos >= textWidth - getWidth()) {
                        //currentScrollPos = -getWidth();
                        task.cancel();
                        flag = true;
                        if (marqueeListener != null) {
                            marqueeListener.onFinish();
                        }
                    }

                    if (!flag) {
                        currentScrollPos += 1;
                        scrollTo(currentScrollPos, 0);
                    }
                }
            });
        }
    };

    public MarqueeTextView(Context context) {
        super(context);
        init();
    }

    public MarqueeTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MarqueeTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setSingleLine();
    }

    public void startScroll() {
        reset();
        stopFuture();
        future = pool.scheduleAtFixedRate(task, 0, speed, TimeUnit.MILLISECONDS);
        //removeCallbacks(runable);
        //post(runable);
    }

    public void postStartScroll(int delay) {
        reset();
        stopFuture();
        future = pool.scheduleAtFixedRate(task, delay, speed, TimeUnit.MILLISECONDS);
        //removeCallbacks(runable);
        //postDelayed(runable, delay);
    }

    public void stopScroll() {
        isStop = true;
        stopFuture();
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public void setMarqueeListener(IMarqueeListener marqueeListener) {
        this.marqueeListener = marqueeListener;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (!isMeasured) {
            getTextWidth();
            isMeasured = true;
        }
    }

    private void getTextWidth() {
        Paint paint = this.getPaint();
        String str = this.getText().toString();
        if (TextUtils.isEmpty(str)) {
            textWidth = 0;
        }
        textWidth = (int) paint.measureText(str);
    }

    public void reset() {
        flag = false;
        isStop = false;
        currentScrollPos = 0;
        scrollTo(currentScrollPos, 0);
    }

    public void setText(String str) {
        super.setText(str);
        isMeasured = false;
        invalidate();
    }

    private synchronized void stopFuture() {
        if (future != null && !future.isCancelled()) {
            future.cancel(true);
        }
        if (task != null) {
            task.cancel();
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions