简体   繁体   English

UI在挂锁后在线程中休眠后挂起

[英]UI hangs after sleep in thread after lockcanvas

I´m trying to implement a fractal renderer on android. 我正在尝试在android上实现分形渲染器。 It uses a SurfaceView to display the results. 它使用SurfaceView来显示结果。

I use a seperate Thread for rendering to keep the UI working during processing, but it locks up until unlockCanvasAndPost is called. 我使用单独的线程进行渲染以在处理过程中保持UI正常工作,但它会一直锁定直到调用unlockCanvasAndPost。 Is this the expected behavior? 这是预期的行为吗? How can I keep the UI from locking up? 如何防止UI锁定? In this example I simulate the long processing by Thread.sleep. 在此示例中,我模拟了Thread.sleep的长时间处理。

My SurfaceView-Class looks like this: 我的SurfaceView-Class看起来像这样:

public class MyView extends SurfaceView implements SurfaceHolder.Callback {

RenderThread rt = null;

public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    getHolder().addCallback(this);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    rt = new RenderThread(holder);
    rt.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    rt.setStop();       
}
}

And this is the RenderThread-class: 这是RenderThread类:

public class RenderThread extends Thread {
SurfaceHolder holder;
boolean running = true;

public RenderThread(SurfaceHolder holder) {
    this.holder = holder;       
}

public void setStop() {
    running = false;
}

@Override
public void run() {
    while(running) {
        Canvas canvas = holder.lockCanvas();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(canvas == null) return;

        Paint p = new Paint();
        p.setARGB(255, 255, 0, 0);
        canvas.drawLine(0, 0, 100, 100, p);
        holder.unlockCanvasAndPost(canvas);
    }
}
}

Several possibilities. 几种可能性。

You don't show how you've incorporated your MyView class into the activity that contains it. 您不会显示如何将MyView类合并到包含它的活动中。 Because you've subclassed SurfaceView, you have to add code to your activity to specifically deal with what you've added with RenderThread. 因为已经继承了SurfaceView的子类,所以必须将代码添加到活动中以专门处理使用RenderThread添加的内容。 The activity's onPause() method, for example, should be sending a signal to your MyView class to stop its RenderThread. 例如,活动的onPause()方法应向MyView类发送信号以停止其RenderThread。

The surfaceDestroyed() method gets called just before the SurfaceHolder's surface is destroyed. 在销毁SurfaceHolder的曲面之前,将调用surfaceDestroyed()方法。 You cannot return from that method until your RenderThread has stopped touching it. 在您的RenderThread停止触摸该方法之前,您无法从该方法返回。 This is accomplished through synchronization. 这是通过同步来完成的。 Official Android documentation for surfaceDestroyed() . 适用于surfaceDestroyed()的官方Android文档

There's a terrific example of how all of this is properly done in WindowSurface.java in the ApiDemos project (for Eclipse, installed with "Samples for SDK" via the Android SDK Manager). 有一个极好的示例,说明如何在ApiDemos项目的WindowSurface.java中正确完成所有这些操作(对于Eclipse,通过Android SDK Manager与“ Samples for SDK”一起安装)。 Once you've loaded the project into Eclipse (with File->New->Project->Android Sample Project), find WindowSurface.java in com.example.android.apis.graphics within the project. 将项目加载到Eclipse后(通过File-> New-> Project-> Android Sample Project),在项目内com.example.android.apis.graphics中找到WindowSurface.java。

Finally, if your actual code in the thread's run method (what you've replaced with Thread.sleep in the interest of brevity here) does anything with the canvas then your check for canvas==null should be immediately below the attempted locking of that canvas. 最后,如果线程的run方法中的实际代码(为简洁起见,已将其替换为Thread.sleep)对画布进行了任何操作,则您对canvas == null的检查应立即低于尝试锁定的范围帆布。 Ideally, it's better form to do that anyway. 理想情况下,无论如何最好这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM