2010-03-12 1 views
4

Я пытаюсь найти способ правильно обработать настройку активности, где ее ориентация определяется из данных в намерении, которое запустило его. Это для игры, где пользователь может выбирать уровни, некоторые из которых являются ориентацией на портрет, а некоторые - ориентацией на пейзаж. Проблема, с которой я сталкиваюсь, заключается в том, что setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) не вступает в силу до тех пор, пока активность не будет полностью загружена. Это проблема для меня, потому что я выполняю загрузку и обработку изображений во время запуска, что я хотел бы сделать только один раз.Изящно обрабатывая изменение ориентации экрана во время запуска активности

В настоящее время, если пользователь выбрал уровень пейзажа:

  • активность начинается OnCreate(), по умолчанию портрета
  • обнаруживает из анализа его запуск Intent, что она должна быть в альбомной ориентации
  • продолжается независимо от пути до onResume(), загрузки информации и выполнения других задач настройки
  • в этот момент setRequestedOrientation запускается так, чтобы приложение выполнялось через onPause() в onDestroy()
  • тогда снова запускается из OnCreate() и бежит к onResume() повторяет установку из ранее

Есть ли способ избежать этого и он не выполняет загрузку в два раза? Например, в идеале, активность будет знать, прежде чем даже onCreate был вызван, должен ли он быть пейзаж или портрет в зависимости от какого-либо свойства намерения запуска, но если я не пропустил что-то, что невозможно. Мне удалось взломать способ избежать повторения загрузки, проверив boolean до трудоемких этапов загрузки, но это не похоже на правильный способ его выполнения. Я предполагаю, что могу переопределить onSaveInstanceState, но для этого потребуется много дополнительного кодирования. Есть ли простой способ сделать это?

Спасибо!


Решение:

Согласно ответу Даниила, это было на самом деле довольно легко исправить. Мне просто нужно было внести несколько небольших изменений. В моем «меню», где игрок выбирает, какой уровень играть, мне просто пришлось добавить проверку if/else, чтобы выбрать, какой класс будет запущен моим намерением. Это было сделано с помощью простого int, представляющего портрет или пейзаж, определяемый, когда игрок выбрал уровень. Затем я создал второй класс, расширяющий класс GameLogic; это класс, который содержит большую часть кода для самой игры, а не меню, инструкции и т.д.

public class GameLandscape extends GameLogic{ 
} 

Буквально так просто и совершенно пустой. Таким образом, он унаследовал весь код от моей предыдущей деятельности, где я уже закодировал ее, чтобы обрабатывать вещи по-разному в зависимости от ориентации. Наконец, мне просто пришлось добавить строку в манифест, в котором говорилось, что GameLandscape всегда будет работать в ландшафте, а GameLogic всегда будет работать на портрете.

Так просто проблема.

ответ

6

Вы можете сделать две операции - одну для портретных уровней, другую для уровней ландшафта - и затем установить ориентацию Activity в AndroidManifest.xml, используя атрибут android:screenOrientation. Вам даже не придется дублировать код, если вы используете наследование; используйте свою текущую деятельность как базовую активность и просто создайте пейзаж/портретные действия как подклассы этой деятельности.

Я думаю, что лучшим решением было бы для намерения открыть правильную деятельность этих двух, хотя, если вы должны прогнать все через дополнительный анализ Intent, вы можете перенаправить все уровни на третью операцию, которая делает не что иное, как проанализируйте Намерение, а затем переместите его на соответствующую Деятельность.

+0

Это хорошая идея, спасибо. Я отдам это. (Я не уверен, как мне понадобится третье мероприятие - да, мне нужно обработать намерение, чтобы получить другую информацию, хранящуюся в дополнительных приложениях, но этот код уже существует в моей деятельности. Если вы имели в виду, что мне может понадобиться 3-я операция, чтобы выбрать, какой из них отправить, а затем я мог бы просто сделать это, когда начнём хранить ориентацию в дополнительных функциях. Где я не понимаю эту часть вашего ответа?: P) –

+0

Ну, вы сказали, как вы используете намерение определить, должно ли быть в ландшафтном или портретном режиме. Если вам действительно нужно это сделать, вы можете использовать третью операцию для ее анализа, а затем переслать ее. Но, как я уже сказал, лучшим решением было бы для намерения просто назвать правильную ориентацию в первую очередь. (Извините, если мой ответ немного запутанный). –

+0

Это работало с удовольствием и было просто невозможно реализовать. Детали добавляются ниже моего вопроса для кого-то другого, у кого такая же проблема. –

2

Вы также можете переопределить onRetainNonConfigurationInstance(). Это позволяет временно сохранить один элемент, который вы можете получить, вызвав getLastNonConfigurationInstance(). Таким образом, вы можете загрузить все необходимое, а в своем методе onRetainNonConfigurationInstance() вы можете сохранить все это в структуре данных и вернуть его. В вашем onCreate() вы можете позвонить getLastNonConfigurationInstance(), и если это возвращает нулевую нагрузку, загрузите все свои вещи, если оно что-то вернет, тогда вы все загрузите. Вот краткий пример:

public class MyActivity extends Activity 
{ 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     DataStructure myData = (DataStructure)getLastNonConfigurationInstance(); 
     if(myData == null) 
     { 
      // Load everything in 
     } 
     else 
     { 
      // Unpack myData 
     } 
    } 

    @Override 
    public Object onRetainNonConfigurationInstance() 
    { 
     DataStructure myData = new DataStructure(); 
     // Put everything in to myData 
     return myData; 
    } 
} 
+0

Ах да, я забыл о onRetainNonConfigurationInstance, но это решение похоже в целом похоже на переопределение onSaveInstanceState. Оба потребуют немного работы, чтобы убедиться, что я правильно сохранил все. Решение Даниэля выше просто намного проще сделать, поэтому я его выбрал. –

+0

Это правильный способ делать такие вещи, когда вам нужно сделать предварительную обработку один раз. – MrSnowflake

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