美文网首页Java 杂谈UIAndroid技术知识
SurfaceView之懂你竟花光了我所有的气力

SurfaceView之懂你竟花光了我所有的气力

作者: 一只小松 | 来源:发表于2017-07-07 18:15 被阅读0次

楼主最近被surfaceView困扰已久,经过撸主一番苦战,终于发现了问题的所在(可我还是无法解决问题)。
故事是这样的,某巨有钱XX教育公司需要做一款教育视频直播的软件,需要PPT白板区,一番技术选型后,决定采用某易的在线直播SDK,呵呵呵,挖坑的日子开始啦。
迭代了几个版本之后,却一直有个问题困扰着我们这群苦逼的Android开发(你知道我们有多苦吗,加班连调休都没有啊,没有,没 **【您的发言包含凹槽等恶意词汇,已被系统自动屏蔽】),ios上基本能同步绘制PC端的白板,android上就不行了,一直有延迟存在,绘制内容越多延迟越严重,特么这可真是苦了Android开发啊,我特么容易吗?
本着男人怎么能说自己不行呢的指导精神,一个礼拜的鏖战之后,卤煮终于发现了端倪,竟然不是某易的锅,Android surfaceView绘图机制就是如此啊,压根无法做到实时的绘制。诶,男人到了一定的年纪,不承认不行还是不行啊,还是得服老啊。

@Override
public Canvas lockCanvas(Rect inOutDirty) {
    return internalLockCanvas(inOutDirty);
}

private final Canvas internalLockCanvas(Rect dirty) {
    mSurfaceLock.lock();// 使用可重入锁进行多线程控制,同一个线程可以重入,我们目前使用的是单线程绘图;某易使用的多线程绘图,有个毛线用啊,到这里你还不是得认怂(吐槽某易的推锅套路,丫丫,这不是我们SDK的内容,请自由发挥。挥你个mmp)

    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
            + mDrawingStopped + ", win=" + mWindow);

    Canvas c = null;
    if (!mDrawingStopped && mWindow != null) {
        try {
            c = mSurface.lockCanvas(dirty);// 这个lockCanvas才是真正加锁获取canvas
        } catch (Exception e) {
            Log.e(LOG_TAG, "Exception locking surface", e);
        }
    }

    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c);
    if (c != null) {
        mLastLockTime = SystemClock.uptimeMillis();// 标记当前加锁获得canvas的时间戳
        return c;
    }

    // If the Surface is not ready to be drawn, then return null,
    // but throttle calls to this function so it isn't called more
    // than every 100ms.
    // 这里才是重点,如果没有获取到canvas,则下一次请求获取canvas会被延迟到上一次获取成功时间戳的100ms之后,这特么才是导致绘图慢的根本原因
    long now = SystemClock.uptimeMillis();
    long nextTime = mLastLockTime + 100;
    if (nextTime > now) {
        try {
            Thread.sleep(nextTime-now);
        } catch (InterruptedException e) {
        }
        now = SystemClock.uptimeMillis();
    }
    mLastLockTime = now;
    mSurfaceLock.unlock();

    return null;
}

上面的故事告诉我们,不懂就看源代码,不懂就看源代码,不懂就看源代码。

那么这里,一个小问题,看看大家对多线程的理解是否到位了呢?

public class Test {
    private Lock lock = new ReentrantLock();   
    public static void main(String[] args)  {
        Test test = new Test();
        MyThread thread1 = new MyThread(test);
        MyThread thread2 = new MyThread(test);
        thread1.start();
        thread2.start();
 
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.interrupt();
    }  
 
    public void insert(Thread thread) throws InterruptedException{
        lock.lockInterruptibly();   //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
        try {  
            System.out.println(thread.getName()+"得到了锁");
            long startTime = System.currentTimeMillis();
            for(;;) {
                if(System.currentTimeMillis() - startTime >= Integer.MAX_VALUE)
                    break;
                //插入数据
            }
        }
        finally {
            System.out.println(Thread.currentThread().getName()+"执行finally");
            lock.unlock();
            System.out.println(thread.getName()+"释放了锁");
        }  
    }
}
 
class MyThread extends Thread {
    private Test test = null;
    public MyThread(Test test) {
        this.test = test;
    }
    @Override
    public void run() {
 
        try {
            test.insert(Thread.currentThread());
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName()+"被中断");
        }
    }
}

上面这段代码会输出什么呢???大家评论区里自由回复吧。

相关文章

网友评论

    本文标题:SurfaceView之懂你竟花光了我所有的气力

    本文链接:https://www.haomeiwen.com/subject/fqhrhxtx.html