2015-04-11 2 views
1

При нажатии на Android-действие на задний план (нажатие кнопки перехода на приложение или кнопка «домой») приложение немедленно сработает («К сожалению, приложение остановилось»).Сбой активности Android при переключении приложения

Моя деятельность выглядит следующим образом:

public class MyActivity extends Activity { 
    MyView myView; 

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

мнение в вопросе использует нить для рисования:

public class MyView extends SurfaceView implements SurfaceHolder.Callback 
{ 
    protected Engine engine; 

    protected SurfaceHolder surfaceHolder; 
    protected Context context; 

    private PaintThread thread; 

    void initView() { 
     // Initialize our screen holder 
     SurfaceHolder holder = getHolder(); 
     holder.addCallback(this); 

     // Get screen size 
     DisplayMetrics displayMetrics = new DisplayMetrics(); 
     ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); 

     // Initialize engine 
     engine = new Engine(displayMetrics.widthPixels, displayMetrics.heightPixels); 
     engine.init(context); 

     thread = new PaintThread(holder, context, new Handler(), engine); 
     setFocusable(true); 
    } 

    public MyView(Context context, AttributeSet attrs, int defStyle){ 
     super(context, attrs, defStyle); 
     this.context = context; 
     initView(); 
    } 

    public MyView(Context context, AttributeSet attrs){ 
     super(context, attrs); 
     this.context = context; 
     initView(); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {} 

    @Override 
    public void surfaceDestroyed(SurfaceHolder arg0) { 
     Log.i("app", "here!"); 
     boolean retry = true; 

     thread.state = PaintThread.PAUSED; 
     while (retry) { 
      try { 
       thread.join(); 
       retry = false; 
      } catch (InterruptedException e) {} 
     } 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder arg0) { 
     if (thread.state == PaintThread.PAUSED){ 
      thread = new PaintThread(getHolder(), context, new Handler(), engine); 
      thread.start(); 
     } else { 
      thread.start(); 
     } 
    } 
} 

И нить работает так:

public class PaintThread extends Thread { 
    private SurfaceHolder surfaceHolder; 
    private Handler handler; 
    private Context context; 

    private Engine engine; 

    public int state = 1; 

    public final static int RUNNING = 1; 
    public final static int PAUSED = 2; 

    public PaintThread(SurfaceHolder surfaceHolder, Context context, Handler handler, 
         Engine engine) { 
     this.surfaceHolder = surfaceHolder; 
     this.handler = handler; 
     this.context = context; 

     this.engine = engine; 
    } 

    @Override 
    public void run() { 
     long previousUpdate = System.nanoTime(); 
     long beforeTime; 
     long passedTime; 
     long accumulator = 0; 
     long dt = 1000/60; 

     while (state == RUNNING) { 
      beforeTime = System.nanoTime(); 
      passedTime = TimeUnit.MILLISECONDS.convert(beforeTime - previousUpdate, TimeUnit.NANOSECONDS); 
      previousUpdate = beforeTime; 

      accumulator += passedTime; 

      while (accumulator >= dt) { 
       engine.update(dt); 
       accumulator -= dt; 
      } 

      Canvas c = null; 
      try { 
       c = surfaceHolder.lockCanvas(null); 

       synchronized (surfaceHolder) { 
        c.drawColor(Color.WHITE); 
        engine.draw(c); 
       } 
      } finally { 
       if (c != null) { 
        surfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 
} 

Журнал сообщение в представлении его surfaceDestroyed метод отображается, когда одна из этих кнопок нажата, но t он в любом случае приложение падает со следующим сообщением:

java.lang.NullPointerException: Попытка вызвать виртуальный метод «недействительный android.graphics.Canvas.drawColor (INT)» на нулевой ссылке на объект

Пострадавшая линия от метода PaintThread его run:

c.drawColor(Color.WHITE); 

Похоже lockCanvas это в тот момент, не возвращая Canvas мы можем работать с. Это похоже на предполагаемое поведение, когда холст помещается в фоновом режиме при нажатии одной из этих кнопок.

Но это все происходит только перед тем, как поток приостановлен. Что-то не так с установкой, что это происходит или как это можно предотвратить?

ответ

4

оператор if, проверяющий, является ли c нулевым, прежде чем мы его используем?

+0

Doh. Я думал, что я делаю что-то неправильно, но это, по-видимому, только то, как работает поиск на холсте. Есть ли какие-либо предположения о том, почему он возвращает нуль в этот момент? – Elias

2

Я просто столкнулся с аналогичной ситуацией с OP, и мое исправление заключалось в том, чтобы поставить утверждение If вокруг кодов, которые рисуют на холсте.

if (canvas != null) { 
     // draw on canvas 
} 

Надеюсь, что это поможет всем, кто это читает!

Смежные вопросы