Android:启动结果的新活动时无响应的线程

时间:2014-08-17 05:36:42

标签: android multithreading android-activity surfaceview

我是Android的新手所以我正在制作一本着色书应用程序,只是为了让自己熟悉Android编程。我已经广泛查找了我的问题并实施了解决方案,但仍然没有进展。

我有一个活动'ColoringActivity',它调用了一个扩展surfaceview的类'PaintView'。我试图在一个单独的线程中更新画布。我在布局中也有一个按钮,用户可以选择其他活动来挑选颜色。问题是当用户在选择颜色后返回时,画布变空,我不能再画在画布上了。我想我在某种程度上放松了活动之间的线程,虽然线程在后台运行,但我无法访问它。

我在这个论坛上看到我必须在线程类中实现pause()和resume()方法,并且当我转到另一个活动时基本上杀死线程并在我返回时重新启动它。另外我读过我必须覆盖activity类中的onPause()和onResume()方法,并在onResume()中构造surfaceview,以便每次用户返回此活动时构造它。

我很抱歉,如果它没有多大意义,因为我也迷失了。

我的'ColoringActivity':

package com.ali.coloryourself;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class ColoringActivity extends Activity {

private static final int COLOR_REQUEST_CODE = 100;
public static String file;
public static Bitmap bitmap;
BitmapFactory.Options options;
PaintView paintView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_draw);

    Intent intent = getIntent();
    file = intent.getStringExtra("fileName");

//      paintView = (PaintView) findViewById(R.id.drawingSurface);


}

@Override
protected void onResume() {
    paintView = (PaintView) findViewById(R.id.drawingSurface);
    paintView.getThread().resume();
    super.onResume();
}

@Override
protected void onPause() {
    paintView.getThread().pause();
    super.onPause();
}

public void pickColor(View v) {
    paintView.getThread().pause();
    Intent colorIntent = new Intent(this, ColorPickerActivity.class);
    startActivityForResult(colorIntent, COLOR_REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != RESULT_CANCELED) {
        if (requestCode == COLOR_REQUEST_CODE) {
            int color = data.getIntExtra("Color", -1);
//              paintView.getPaint().setColor(color);
        }
    }

}

}

我的'PaintView'课程:

package com.ali.coloryourself;

import android.R.color;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class PaintView extends SurfaceView implements SurfaceHolder.Callback {
private Paint paint = new Paint();
private Canvas canvas;
private PaintThread thread;
private Path path = new Path();

private Bitmap bitmap;

public PaintView(Context context, AttributeSet attrs) {
    super(context, attrs);

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);

    paint.setColor(Color.WHITE);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeCap(Paint.Cap.ROUND);
    paint.setStrokeWidth(3);

    setThread(new PaintThread(holder));
}

class PaintThread extends Thread {
    private boolean mRun;
    private SurfaceHolder mSurfaceHolder;
    private int mMode;

    public static final int STATE_PAUSE = 2;
    public static final int STATE_RUNNING = 4;

    public PaintThread(SurfaceHolder surfaceHolder) {
        mSurfaceHolder = surfaceHolder;
    }

    @Override
    public void run() {
        while (mRun) {
            try {
                canvas = mSurfaceHolder.lockCanvas(null);
                if (mMode == STATE_RUNNING) {
                    if (bitmap == null) {
                        bitmap = Bitmap.createBitmap(1, 1,
                                Bitmap.Config.ARGB_8888);
                    }
                }
                doDraw(canvas);
                canvas.drawBitmap(bitmap, 0, 0, null);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (canvas != null) {
                    mSurfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }

    private void doDraw(Canvas canvas) {
        canvas.drawPath(path, paint);
    }

    public void setRunning(boolean b) {
        mRun = b;
    }

    public void pause() {
            if (mMode == STATE_RUNNING)
                setState(STATE_PAUSE);
    }

    public void resume() {
        setState(STATE_RUNNING);
    }

    public void setState(int mode) {
        synchronized (mSurfaceHolder) {
            mMode = mode;
        }
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // Log.d("Touch", "I am touching");
    float eventX = event.getX();
    float eventY = event.getY();

    int action = event.getAction();

    switch (action) {
    case MotionEvent.ACTION_DOWN:
        path.moveTo(eventX, eventY);
        return true;
    case MotionEvent.ACTION_MOVE:
        path.lineTo(eventX, eventY);
        break;
    case MotionEvent.ACTION_UP:
        // nothing to do
        break;
    default:
        return false;
    }
    return true;
}

public void surfaceCreated(SurfaceHolder holder) {
    if (getThread().getState() == Thread.State.NEW) {
        getThread().setRunning(true);
        getThread().start();
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    getThread().setRunning(false);
    getThread().resume();
    while (retry) {
        try {
            getThread().join();
            retry = false;
        } catch (InterruptedException e) {
        }
    }
}

public Paint getPaint() {
    return paint;
}

public void setPaint(int color) {
    this.paint.setColor(color);
}

public PaintThread getThread() {
    return thread;
}

public void setThread(PaintThread thread) {
    this.thread = thread;
}

}

我的'activity_draw.xml'

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

 <Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="10dp"
    android:onClick="pickColor"
    android:text="Pick Color" />

<com.ali.coloryourself.PaintView
    android:id="@+id/drawingSurface"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:layout_below="@+id/button1"
    android:layout_marginTop="10dp"/>

</RelativeLayout>

我知道我缺少一些非常基本的线程概念。我需要允许用户选择颜色并返回并能够继续绘图。我将非常感谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我想我找到了答案,虽然我不确定它是不是一个好的编程习惯。我发现我的表面视图和线程是在“ColoringActivity”创建并在每次“ColoringActivity”转到背景时被创建时创建的。但是一旦'ColoringActivity'重新启动并恢复,表面视图和线程就不会被重新创建。所以我移动了以下行

setContentView(R.layout.activity_draw);

到onResume()方法,现在我每次都可以在画布上绘图。现在我只需要保存画布并在活动重新开始时重新加载它以开始用户离开它的着色。