2016-05-08 1 views
-1

У меня есть основное действие, которое имеет две конфигурации, в которых будет отображаться фрагмент, который заблокирован для портретной ориентации.Android: как предотвратить очистку переменных класса при изменении ориентации?

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

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

Вот основной вид деятельности:

пакет mobileapp.group2.fragmenttest;

import android.content.pm.ActivityInfo; 
import android.content.res.Configuration; 
import android.support.v4.app.FragmentActivity; 
import android.os.Bundle; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.view.View; 
import android.widget.FrameLayout; 
import android.widget.Toast; 

public class MainActivity extends FragmentActivity 
    implements ListPeersFragment.ListPeersFragmentListener 
{ 
    public static final String LIST_FRAGMENT_TAG = "ListPeersFragment"; 
    public static final String GAME_FRAGMENT_TAG = "GameFragment"; 
    public static final String OPP_FRAGMENT_TAG = "ViewOpponentFragment"; 

    // FrameLayout references 
    private FrameLayout mLeftFrame; 
    private FrameLayout mRightFrame; 

    // Fragment references 
    private ListPeersFragment mListPeersFragment = null; 
    private GameFragment  mGameFragment  = null; 
    private ViewOppFragment mViewOppFragment = null; 

    // Boolean denoting if currently in game mode. 
    //private boolean mGameMode; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mLeftFrame = (FrameLayout) findViewById(R.id.left_frame); 
     mRightFrame = (FrameLayout) findViewById(R.id.right_frame); 

     // However, if we're being restored from a previous state, 
     // then we don't need to do anything and should return or else 
     // we could end up with overlapping fragments. 
     if (savedInstanceState != null) { 
      return; 
     } 

     // Create fragments 
     if (mListPeersFragment == null) 
      mListPeersFragment = new ListPeersFragment(); 
     if (mGameFragment == null) 
      mGameFragment = new GameFragment(); 
     if (mViewOppFragment == null) 
      mViewOppFragment = new ViewOppFragment(); 

     // In case this activity was started with special instructions from an 
     // Intent, pass the Intent's extras to the fragment as arguments 
     mListPeersFragment.setArguments(getIntent().getExtras()); 

     // Add the fragment to the 'fragment_container' FrameLayout 
     FragmentManager fm = getSupportFragmentManager(); 
     fm.beginTransaction().add(R.id.left_frame, mListPeersFragment, LIST_FRAGMENT_TAG).commit(); 
     fm.beginTransaction().add(R.id.right_frame, mViewOppFragment, OPP_FRAGMENT_TAG).commit(); 

     //mGameMode = false; 
    } 

    // Used to intercept back navigation. 
    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     if (keyCode == KeyEvent.KEYCODE_BACK) { 
      FragmentManager fm = getSupportFragmentManager(); 
      if (fm.findFragmentByTag(GAME_FRAGMENT_TAG) != null) 
      { 
       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
       //FragmentTransaction ft = fm.beginTransaction(); 
       fm.beginTransaction().replace(R.id.left_frame, mListPeersFragment, LIST_FRAGMENT_TAG) 
         .commitAllowingStateLoss(); 
       //mGameMode = false; 
       return true; 
      } 
     } 
     return super.onKeyDown(keyCode, event); 
    } 

    public void startGame() 
    { 
     getSupportFragmentManager().beginTransaction() 
       .replace(R.id.left_frame, mGameFragment, GAME_FRAGMENT_TAG).commit(); 

     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 
     //mGameMode = true; 
    } 

    // Implementation of the ListPeersFragmentListener function onPeerSelected 
    public void onPeerSelected(int position) 
    { 

    } 

} 

Основной файл макета деятельности:

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:orientation="horizontal" > 

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:id="@+id/left_frame" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent"/> 

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:id="@+id/right_frame" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent"/> 

</LinearLayout> 

Пейзаж версия только имеет весов на framelayouts.

Другие классы фрагментов очень просты, они ничего не делают в данный момент.

Неудачный код - метод onKeyDown. Есть ли способ предотвратить повторную инициализацию переменных класса при изменении ориентации? Я рассмотрел обработку изменений конфигурации, но затем файл ландшафтного макета не загружен.

Если кто-то может помочь, очень признателен!

+0

Вы можете 'setRetainInstance (true)', чтобы остановить повторное создание фрагмента при изменении ориентации. http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean) –

+0

начал работу с дизайном MVC – Pomagranite

ответ

0

На самом деле всякий раз, когда меняется ориентация, вызывается метод Oncreate(). Таким образом, чтобы предотвратить очистку переменных, переопределить метод OnConfigurationChange() и в вашем файле манифеста сделать это в своей деятельности: -

android:configChanges="orientation" 
0

Вы должны использовать onSaveInstanceState() и onRestoreInstanceState() методы деятельности, как указано в this link.

Кроме того, вам нужно будет вызвать методы setRetainInstance() в фрагментах, которые вы хотите сохранить.

Отъезд this link для получения дополнительной информации о setRetainInstanceState().