StackoverflowError我的绘制线程不起作用,但我不知道如何处理内存分配

时间:2014-06-22 23:46:17

标签: android multithreading android-canvas stack-overflow

我正在尝试编写一个视频游戏,我想重新绘制背景以模拟地图。 所以为此,我创建了一个新的类,它扩展了surfaceview,一个扩展了一个线程,实现了我需要的所有(我的活动的xml文件中的surfaceview)。但是我有一个小问题,当我setcontentview它自动崩溃时告诉我我有StackOverflowError

首先,我的主要活动代码

public class MainActivity extends Activity {

    float debutX = -1;``
    float debutY = -1;
    float height = 0; // 1280
    float width =0; // 720


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final View img = (View) findViewById(R.id.img);
        final TextView text = (TextView) findViewById(R.id.text);
        final RelativeLayout parent = (RelativeLayout) findViewById(R.id.parent);

        surface surf = (surface)findViewById(R.id.surface);

        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) parent.getLayoutParams();

        surf=new surface(getApplicationContext());
        setContentView(surf,params);


        parent.setOnTouchListener(new OnTouchListener() {

            public boolean onTouch(View v, MotionEvent ev) {
                height=parent.getHeight();
                width=parent.getWidth();

                switch (ev.getActionMasked()) {

                case MotionEvent.ACTION_DOWN:
                    debutX=0;
                    debutY=0;
                    if (zonecorrecte(ev.getX(), ev.getY(), width, height)) {
                        debutX = ev.getX();
                        debutY = ev.getY();
                        text.setText(debutX + ", " + debutY);
                    }
                    break;

                case MotionEvent.ACTION_MOVE:
                    float a = ((ev.getX() - debutX) / 2) + img.getX();
                    float b = (ev.getY() - debutY) / 2 + img.getY();
                    if (danslecranX(a, width, img)) {
                        img.setX(a);
                    }
                    if (danslecranY(b, height, img)) {
                        img.setY(b);
                    }

                    Log.d("Main", a + " " +b);
                    if(img.getX()<=0.2*width &&img.getY()<=0.2*height)
                    {}

                    try {
                        Thread.sleep(40);
                    } catch (InterruptedException e) {}
                    break;

                case MotionEvent.ACTION_UP:         
                    break;

                }

                return true;
            }
        });
    }

和新线程:

package tibo.test5;

@SuppressLint("WrongCall")
public class surface extends SurfaceView implements SurfaceHolder.Callback {

    SurfaceHolder surface = null;
    DrawingThread mThread=new DrawingThread();
    final View img = (View) findViewById(R.id.img);
    Paint p = new Paint();
    Bitmap caro = BitmapFactory.decodeResource(getResources(),R.drawable.caro);

    public void onDraw(Canvas canvas) {

        p.setAntiAlias(true);
        p.setFilterBitmap(true);
        p.setDither(true);

        canvas.drawBitmap(caro, 0, 0, p);
        draw(canvas);

    }

    public surface(Context context) {
        super(context);
        init();
        mThread = new DrawingThread();

    }


    public void init() {
        surface = getHolder();
        surface.addCallback(this);
    }
    public surface(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);

        // TODO:
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mThread.keepDrawing = true;
        mThread.start();

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        mThread.keepDrawing = false;

        boolean joined = false;
        while (!joined) {
            try {
                mThread.join();
                joined = true;
            } catch (InterruptedException e) {
            }
        }

    }

    class DrawingThread extends Thread {

        boolean keepDrawing = true;

        int deb = 0;

        @Override
        public void run() {

            while (keepDrawing) {
                Canvas canvas = null;

                try {
                    canvas = surface.lockCanvas();

                    synchronized (surface) {
                        if(canvas!=null)onDraw(canvas);
                    }
                } finally {

                    surface.unlockCanvasAndPost(canvas);
                }

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        }
    }

我只是希望能够在需要时“刷新”我的表面,但是在第二次开始运行线程时我的游戏被冻结并崩溃无关紧要。

日志:

06-23 01:38:42.751: D/OpenGLRenderer(15394): Enabling debug mode 0
06-23 01:38:42.816: I/dalvikvm(15394): threadid=11: stack overflow on call to Landroid/graphics/Bitmap;.nativeConfig:II
06-23 01:38:42.816: I/dalvikvm(15394):   method requires 4+20+0=24 bytes, fp is 0x61b65308 (8 left)
06-23 01:38:42.816: I/dalvikvm(15394):   expanding stack end (0x61b65300 to 0x61b65000)
06-23 01:38:42.816: I/dalvikvm(15394): Shrank stack (to 0x61b65300, curFrame is 0x61b68fdc)
06-23 01:38:42.816: W/dalvikvm(15394): threadid=11: thread exiting with uncaught exception (group=0x41c75c08)
06-23 01:38:42.851: D/dalvikvm(15394): GC_FOR_ALLOC freed 145K, 15% free 8466K/9920K, paused 14ms, total 14ms
06-23 01:38:42.856: E/AndroidRuntime(15394): FATAL EXCEPTION: Thread-4458
06-23 01:38:42.856: E/AndroidRuntime(15394): Process: tibo.test5, PID: 15394
06-23 01:38:42.856: E/AndroidRuntime(15394): java.lang.StackOverflowError
06-23 01:38:42.856: E/AndroidRuntime(15394):    at android.graphics.Bitmap.getConfig(Bitmap.java:1302)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at android.graphics.Bitmap.isPremultiplied(Bitmap.java:1148)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1086)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at android.graphics.Canvas.drawBitmap(Canvas.java:1139)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at tibo.test5.surface.onDraw(surface.java:29)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at android.view.View.draw(View.java:15410)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at android.view.SurfaceView.draw(SurfaceView.java:349)
06-23 01:38:42.856: E/AndroidRuntime(15394):    at tibo.test5.surface.onDraw(surface.java:30)

所以这是我没有得到的:

我是否处于无限循环中,因为我没有用reume() / pause()处理我的线程,或者我的draw方法是否为图像重新分配内存而不删除某些内容?

我试图添加简历并停止但它没有用,所以我相信我的第二个理论是正确的。

1 个答案:

答案 0 :(得分:0)

您正在进行无限递归(导致堆栈溢出),因为您正在draw()方法中调用onDraw()。而不是子类SurfaceView,只需创建SurfaceHolder.Callback的实例(或让ActivityFragment实现接口)并保留SurfaceHolder的实例。然后在您的主题中,您可以锁定Surface,直接绘制到Canvas,然后调用SurfaceHolder.unlockCanvasAndPost()