Android: не отвечающий поток при запуске нового действия для результата
Я новичок в Android, поэтому я делаю приложение для раскрашивания, чтобы познакомиться с программированием Android. Я тщательно изучил свою проблему и реализовал решения, но все еще не достиг прогресса.
У меня есть действие "ColoringActivity", которое вызывает класс "PaintView", который расширяет вид поверхности. Я пытаюсь обновить холст в отдельной теме. У меня также есть кнопка в макете, которая переводит пользователя в другое занятие для выбора цветов. Проблема в том, что когда пользователь возвращается после выбора цвета, холст становится пустым, и я больше не могу рисовать на холсте. Я думаю, что я каким-то образом теряю поток между действиями, и хотя поток работает в фоновом режиме, у меня нет доступа к нему.
Я прочитал на этом форуме, что я должен реализовать методы pause() и resume() в классе потока и, в основном, убить поток, когда я перехожу к другому действию, и перезапускать его, когда я возвращаюсь. Также я прочитал, что мне нужно переопределить методы onPause() и onResume() в классе действия и создать представление поверхности в onResume(), чтобы оно создавалось каждый раз, когда пользователь возвращается к этому действию.
Прошу прощения, если в этом нет особого смысла, потому что я тоже потерялся.
Моя "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 ответ
Я думаю, что нашел ответ, хотя я не уверен, что это хорошая практика программирования. Я обнаружил, что мой вид поверхности и нить были созданы после того, как ColoringActivity была создана и уничтожена каждый раз, когда ColoringActivity переходила в фоновый режим. Но как только "ColoringActivity" был перезапущен и возобновлен, вид поверхности и резьба не были воссозданы. Итак, я переместил следующую строку
setContentView(R.layout.activity_draw);
метод onResume(), и теперь я могу рисовать на холсте каждый раз. Теперь мне просто нужно сохранить холст и заново загрузить его, когда снова включится действие, чтобы начать раскрашивание, где пользователь оставил его.