楼主最近被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()+"被中断");
}
}
}
上面这段代码会输出什么呢???大家评论区里自由回复吧。
网友评论