仅在特定设备上的SurfaceView中的ANR - 唯一的解决方法是睡眠时间短
在我的Android应用程序中,我使用a来绘制东西。它在数千台设备上工作正常 - 除了现在用户开始在以下设备上报告ANR:SurfaceView
- LG G4
- 安卓 5.1
- 3 GB 内存
- 5.5 英寸显示屏
- 2560 x 1440 px 分辨率
- 索尼Xperia Z4
- 安卓5.0
- 3 GB 内存
- 5,2“ 显示屏
- 1920 x 1080 px 分辨率
- 华为昇腾伴侣7
- 安卓 5.1
- 3 GB 内存
- 6.0 英寸显示屏
- 1920 x 1080 px 分辨率
- 宏达电 M9
- 安卓 5.1
- 3 GB 内存
- 5.0“ 显示屏
- 1920 x 1080 px 分辨率
所以我买了一台LG G4,并且确实能够验证这个问题。它与 .SurfaceView
现在猜猜经过数小时的调试后,是什么解决了问题?它正在取代...
mSurfaceHolder.unlockCanvasAndPost(c);
...跟。。。
mSurfaceHolder.unlockCanvasAndPost(c);
System.out.println("123"); // THIS IS THE FIX
这怎么可能?
以下代码是我的渲染线程,除上述设备外,它一直工作正常:
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MyThread extends Thread {
private final SurfaceHolder mSurfaceHolder;
private final MySurfaceView mSurface;
private volatile boolean mRunning = false;
public MyThread(SurfaceHolder surfaceHolder, MySurfaceView surface) {
mSurfaceHolder = surfaceHolder;
mSurface = surface;
}
public void setRunning(boolean run) {
mRunning = run;
}
@Override
public void run() {
Canvas c;
while (mRunning) {
c = null;
try {
c = mSurfaceHolder.lockCanvas();
if (c != null) {
mSurface.doDraw(c);
}
}
finally { // when exception is thrown above we may not leave the surface in an inconsistent state
if (c != null) {
try {
mSurfaceHolder.unlockCanvasAndPost(c);
}
catch (Exception e) { }
}
}
}
}
}
该代码部分来自Android SDK中的示例,更具体地说。LunarLander
LunarView.java
更新代码以匹配 Android 6.0(API 级别 23)中的改进示例,将产生以下结果:
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MyThread extends Thread {
/** Handle to the surface manager object that we interact with */
private final SurfaceHolder mSurfaceHolder;
private final MySurfaceView mSurface;
/** Used to signal the thread whether it should be running or not */
private boolean mRunning = false;
/** Lock for `mRunning` member */
private final Object mRunningLock = new Object();
public MyThread(SurfaceHolder surfaceHolder, MySurfaceView surface) {
mSurfaceHolder = surfaceHolder;
mSurface = surface;
}
/**
* Used to signal the thread whether it should be running or not
*
* @param running `true` to run or `false` to shut down
*/
public void setRunning(final boolean running) {
// do not allow modification while any canvas operations are still going on (see `run()`)
synchronized (mRunningLock) {
mRunning = running;
}
}
@Override
public void run() {
while (mRunning) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
// do not allow flag to be set to `false` until all canvas draw operations are complete
synchronized (mRunningLock) {
// stop canvas operations if flag has been set to `false`
if (mRunning) {
mSurface.doDraw(c);
}
}
}
}
// if an exception is thrown during the above, don't leave the view in an inconsistent state
finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
但是,此类仍然不适用于上述设备。我出现黑屏,应用程序停止响应。
唯一(我发现的)解决问题的是添加调用。在循环结束时添加较短的睡眠时间,结果结果显示相同的结果:System.out.println("123")
try {
Thread.sleep(10);
}
catch (InterruptedException e) { }
但这些都不是真正的解决方案,不是吗?这不是很奇怪吗?
(根据我对代码所做的更改,我还能够在错误日志中看到异常。有许多开发人员遇到同样的问题,但不幸的是,没有人为我(特定于设备)的情况提供解决方案。
你能帮忙吗?