Android 优化实践系列文章

StrictANR 实现机制

2017-02-06  本文已影响40人  ahking17
实现机制

在子线程中, 得到主线程的handler, 在run()中, 先发一个runnable让主线程去执行, 然后sleep()设定的时间, 然后再检测int _tick的值是否被修改了, 这个runnable的目的就是改变int _tick的值, 如果_tick的值没有得到修改, 就说明发生了strict anr.

public class StrictANRWatchDog extends Thread {

    private final Handler _uiHandler = new Handler(Looper.getMainLooper());
    private final int _timeoutInterval;

    private volatile int _tick = 0;

    public StrictANRWatchDog(int timeoutInterval) {
        super();
        _timeoutInterval = timeoutInterval;
    }
    private final Runnable _ticker = new Runnable() {
        @Override public void run() {
            _tick = (_tick + 1) % Integer.MAX_VALUE;
        }
    };
    //这个runnable对象的目的, 就是让保证int _tick的值发生了改变.

    public interface ANRListener {
        public void onAppNotResponding(StrictANRError error);
    }

    @Override
    public void run() {
        setName("|Strict-ANR-WatchDog|");

        int lastTick;
        int lastIgnored = -1;
        while (!isInterrupted() && _keepTracking) {
            lastTick = _tick;
            _uiHandler.post(_ticker);
    //向主线程的handler发送一个runnable对象去执行.
            try {
            Thread.sleep(_timeoutInterval);
    //sleep设定的时间
            }
            catch (InterruptedException e) {
            _interruptionListener.onInterrupted(e);
            return ;
            }
    //如果int _tick的值没有发生改变, 说明发送给主线程的runnable没有得到及时的执行, 也就是发生了strict anr.
            // If the main thread has not handled _ticker, it is blocked. ANR.
            if (_tick == lastTick) {
            StrictANRError error;
            if (_namePrefix != null)
                error = new StrictANRError(_namePrefix, _logThreadsWithoutStackTrace);
            else
                error = StrictANRError.NewMainOnly();
            _anrListener.onAppNotResponding(error);
            }
        }
        JLog.i("exit Strict ANR WatchDog thread.");
    }

    public void startTracking() {
        if(this.isAlive()) {
            return;
        }

        _keepTracking = true;
        start();
    }
}
使用上很简单

在Application onCreate()中, 创建StrictANRWatchDog 的对象, 并开始检测就可以了.

    private void initStrictANRWatchDog() {
        mWatchDog = new StrictANRWatchDog(mTimeInterval);

        mWatchDog.setANRListener(new StrictANRWatchDog.ANRListener() {
            @Override
            public void onAppNotResponding(StrictANRError error) {
                JLog.i("Strict ANR detected.");
                Message msg = new Message();
                msg.what = MSG_TOAST;
                msg.obj = "Strict ANR detected.";
                mHandler.sendMessage(msg);

                error.printAllStackTrace();
            }
        });
        mWatchDog.startTracking();
    }

-----DONE.--------------------------

上一篇下一篇

猜你喜欢

热点阅读