Недавно я с программирования приложений на java для android перешёл на игры. И тут же возникла очень большая проблема: при первом заходе в игру всё нормально, но если нажать кнопку "назад" или "домой", не закрывая окна, а затем снова открыть игру, в ней ничего нет - только пустое окно. Чего я только не перепробовал - ничего не получилось. Я начинающий девелопер, и прошу не судить за мою тупость, если таковая имеет место быть.
Код:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new DrawView(this));
}
class DrawView extends SurfaceView implements SurfaceHolder.Callback{
private DrawThread drawThread;
private Player player;
public DrawView(Context context) {
super(context);
getHolder().addCallback(this);
drawThread = new DrawThread(getHolder(),this);
player = new Player(BitmapFactory.decodeResource(getResources(), R.drawable.player), 10, 10);
setFocusable(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread.setRunning(true);
drawThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void onDraws(Canvas canvas){
canvas.drawColor(Color.rgb(0, 80, 0));
player.draws(canvas);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry){
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
player.handleActionDown((int) event.getX(), (int) event.getY());
}
if (event.getAction() == MotionEvent.ACTION_MOVE){
if (player.isTouched()){
player.setX((int) event.getX());
player.setY((int) event.getY());
}
}
if (event.getAction() == MotionEvent.ACTION_UP){
if (player.isTouched) player.setTouched(false);
}
return true;
}
}
class DrawThread extends Thread {
private boolean running = false;
private SurfaceHolder surfaceHolder;
private DrawView drawView;
public DrawThread(SurfaceHolder surfaceHolder, DrawView drawView){
this.surfaceHolder = surfaceHolder;
this.drawView = drawView;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Canvas canvas;
while (running){
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
if (canvas == null) continue;
drawView.onDraws(canvas);
}
}finally {
if (canvas != null) surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
class Player{
private Bitmap bitmap;
private int x;
private int y;
private boolean isTouched;
public Player(Bitmap b, int x, int y){
this.bitmap = b;
this.y = y;
this.x = x;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setTouched(boolean touched) {
isTouched = touched;
}
public boolean isTouched() {
return isTouched;
}
public void draws(Canvas canvas){
canvas.drawBitmap(bitmap, x - bitmap.getWidth()/2, y - bitmap.getHeight()/2, null);
}
public void handleActionDown(int eventX, int eventY){
if (eventX >= x - bitmap.getWidth() / 2 && eventX <= x + bitmap.getWidth() / 2 &&
eventY >= y - bitmap.getHeight() / 2 && eventY <= y + bitmap.getHeight() / 2) setTouched(true);
else setTouched(false);
}
}
}
surfaceDestroyed
вызывается каждый раз, когда SurfaceView
перестаёт быть виден на экране. В нём Вы завершаете поток рисования. Но один экземпляр потока может быть запущен только один раз. Когда он завершился, то запустить его повторно нельзя - нужно создавать новый экземпляр:
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawThread = new DrawThread(getHolder(),this);
drawThread.setRunning(true);
drawThread.start();
}
P.S. Не знаю зачем Вам эта конструкция:
while (retry){
try {
drawThread.join();
retry = false;
} catch (InterruptedException e) {}
}
но останавливать любым способом и сильно нагружать главный поток на Андроиде крайне нежелательно.
P.P.S. А проблема то как раз ещё и в этой конструкции - она блокирует главный поток и ждёт завершения рисующего, но рисующий не останавливается так как ему не вызван drawThread.setRunning(false);
и он даже не знает что надо прекратить работу. В результате главный поток не может ни завершить ни восстановить работу активити
Во первых, я бы избавился от анонимности DrawView и перенес бы его в разметку.
<com.example.DrawView
android:id="@+id/draw_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Затем в активити определил бы его.
public class MainActivity extends AppCompatActivity {
private DrawView drawView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dravView = findViewById(R.id.draw_view);
}
}
Далее внес бы изменения в само DrawView
class DrawView extends SurfaceView implements SurfaceHolder.Callback{
//ваши поля
/*без этого конструктора в разметке ваше View не разместить*/
public DrawView(Context context,@Nullable AttributeSet attrs) {
super(context,attrs);
}
/*этим методом все запускаете*/
public voyd play(){
getHolder().addCallback(this);
drawThread = new DrawThread(getHolder(),this);
player = new Player(BitmapFactory.decodeResource(getResources(),
R.drawable.player), 10, 10);
setFocusable(true);
{
//остальной код
}
В MainActivity переопределяем onStart()
@Override
protected void onStart() {
super.onStart();
drawView.play();
}
Вроде так. На машине не тестил, но должно помочь. Хотя в принципе, при нажатии кнопки Back то таких нюансов не должно было быть..
Виртуальный выделенный сервер (VDS) становится отличным выбором
Хочу сделать так что бы JS определял Ip пользователя при запуске скрипта, но не знаю как это сделатьПодскажете?
Столкнулась с проблемой, что изображение, получаемое из canvas, не добавляется в поле imageКод следующий (VueJS v