У меня есть приложение, использующее GlSurfaceView и средство визуализации. У меня установлено так, что когда пользователь выходит из приложения через кнопку назад, я вызываю myActivity.finish ();
Это нормально, и я вижу, как активность вызывает вызовы onStop () и onDestroy ();
Приложение работает нормально при первом запуске, однако при последующем запуске у меня возникла проблема с motionEvents.
Я обрабатываю события движения, помещая их в очередь в пул и позволяя средству рендеринга обращаться к пулу в нужное время следующим образом:
try
{
//Get the history first
int hist = event.getHistorySize();
if (hist > 0)
{
//Oldest is first in the list. (I think).
for (int i=0;i <hist; i++)
{
InputObject input = inputObjectPool.take();
input.useEventHistory(event, i);
defRenderer.feedInput(input);
}
}
//The current one still needs to be added
InputObject input = inputObjectPool.take();
input.useMotionEvent(event);
defRenderer.feedInput(input);
}
А в рендере:
synchronized (inputQueueMutex)
{
ArrayBlockingQueue<InputObject> inputQueue = this.inputQueue;
while (!inputQueue.isEmpty()){try
{
InputObject input = inputQueue.take();
if (input.eventType == InputObject.EVENT_TYPE_TOUCH)
{
screenManager.processMotionEvent(input);
}
else if (input.eventType == InputObject.EVENT_TYPE_KEY)
{
screenManager.processKeyPress(input);
}
input.returnToPool();
}
catch (InterruptedException ie)
{
DLog.defError("Interrupted blocking on input queue.", ie);
}
}
}
Как вы можете видеть из приведенного выше кода, я передаю эти события движения в ScreenManager, который, по сути, является моим способом создания нескольких "сцен", которые я отрисовываю. Это отлично работает при первом запуске приложения, и экран интерпретирует мои движения в настоящий момент как простой квадрат.
Тем не менее, во второй раз, когда я запускаю приложение, квадрат хорошо отображается на экране, однако события движения ничего не делают.
Я следил за событиями движения, и хотя они передаются «новому» средству визуализации, похоже, что они передают события движения на старый экран. Или скорее к старому объекту на экране. Это сбивает с толку, так как в моем коде в методе onCreate () я делаю это:
//Set up the renderer and give it to the SurfaceView
defRenderer = new DefRenderer();
defView = new DefView(this);
defView.setRenderer(defRenderer);
//Set out content to the surface view.
setContentView(defView);
//Set up the input queue
createInputObjectPool();
OnCreate вызывается как в первый раз, так и во второй раз, когда мое приложение запускается (и приложение было уничтожено!), Экраны становятся новыми в defRenderer и передаются новому defView.
Я очень озадачен тем, как данные могут остаться в defRenderer для получения motionEvents, поскольку приложение полностью переделано.
Есть ли что-то очевидное, что я здесь упускаю? Я бы подумал, что при вызове onDestroy приложение будет полностью разыменовано, и от него не останется никаких следов. Это не правда? Делает ли что-то, когда я вызываю новый Renderer (); это ссылка на старую?
Я в растерянности относительно того, что происходит на самом деле. Тем более, что это приложение является базовой копией другого, которое я написал, и оно прекрасно работает!
EDIT:
После небольшого количества экспериментов я обнаружил, что события движения на самом деле идут к старой ScrollPanel (объект, который я сделал ..), который зарегистрирован как слушатель (и под слушателем я имею в виду мою собственную реализацию ..) для MotionEvents. Я сделал для них свою собственную систему событий:
public interface TouchSource
public static final int TYPE_TOUCHDOWN = 0;
public static final int TYPE_TOUCHDRAG = 1;
public static final int TYPE_TOUCHCLICK = 2;
public Vector<TouchListener> listeners = new Vector<TouchListener>();
public void addTouchListener(TouchListener listener);
public void removeTouchListener(TouchListener listener);
public void touchOccured(int type, int xPos, int yPos);
}
И интерфейс слушателя:
public interface TouchListener
public boolean touchDownOccured(int xPos, int yPos);
public boolean touchDragOccured(int xPos, int yPos);
public boolean touchClickOccured(int xPos, int yPos);
Таким образом, Screen реализует touchSource и, таким образом, имеет список слушателей. Теперь несмотря на то, что REMADE by Screen currentScreen = new Screen (); вызывается в OnCreate (); менеджера этот список слушателей до сих пор заполнен старой ScrollPanel?
Как это? Я явно упускаю что-то очевидное. Например, список слушателей по какой-то причине статичен и не получает разыменования, несмотря на то, что приложение полностью переделано?