Надежный способ обработки фрагмента при изменении ориентации


87
public class MainActivity extends Activity implements MainMenuFragment.OnMainMenuItemSelectedListener {

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

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager
            .beginTransaction();

    // add menu fragment
    MainMenuFragment myFragment = new MainMenuFragment();
    fragmentTransaction.add(R.id.menu_fragment, myFragment);

    //add content
    DetailPart1 content1= new DetailPart1 ();
    fragmentTransaction.add(R.id.content_fragment, content1);
    fragmentTransaction.commit();

}
public void onMainMenuSelected(String tag) {
  //next menu is selected replace existing fragment
}

Мне нужно отображать два списка рядом, меню слева и его содержимое справа. По умолчанию выбрано первое меню, и его содержимое отображается справа. Фрагмент, отображающий содержимое, выглядит следующим образом:

public class DetailPart1 extends Fragment {
  ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
  ListAdapter adap;
  ListView listview;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);

       if(savedInstanceState!=null){
        myList = (ArrayList)savedInstanceState.getSerializable("MYLIST_obj");
        adap = new LoadImageFromArrayListAdapter(getActivity(),myList );
        listview.setAdapter(adap);
       }else{
        //get list and load in list view
        getlistTask = new GetALLListTasks().execute();
    }


     @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.skyview_fragment, container,false);
           return v;
        }


     @Override
      public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
          outState.putSerializable("MYLIST_obj", myList );
        }
    }

OnActivityCreated и onCreateView вызываются дважды . Есть много примеров использования фрагментов. Поскольку я новичок в этой теме, я не могу связать этот пример со своей проблемой. Мне нужен надежный способ справиться с изменением ориентации. Я НЕ указывал android:configChangesв файле манифеста. Мне нужно уничтожить и воссоздать действие, чтобы я мог использовать другой макет в ландшафтном режиме.


Обычно об изменении ориентации фрагментов заботятся без каких-либо дополнительных действий. Итак, с какой проблемой вы сталкиваетесь, когда меняете ориентацию?
Александр Куляхтин 09

Alex Мне нужен фрагмент класса DetailPart1 для отображения макета с помощью listView в портретном режиме и макета с Grid View в альбомном режиме. Для этого мне нужно каждый раз воссоздавать фрагмент, но я не хочу снова загружать одни и те же записи, поэтому я сохраните их в onSaveInstanceState. Но приведенный выше код дважды воссоздает DetailPart1, мне нужно знать недостающий код, который заставляет его работать
должным образом

Ответы:


132

Вы создаете новый фрагмент каждый раз, когда поворачиваете экран в своей деятельности, onCreate();но вы также сохраняете старые с помощью super.onCreate(savedInstanceState);. Так что, возможно, установите тег и найдите фрагмент, если он существует, или передайте нулевой пакет в super.

Мне потребовалось время, чтобы научиться этому, и это действительно может быть сутью, когда вы работаете с такими вещами, как viewpager.

Я бы порекомендовал вам прочитать о фрагментах еще раз, так как эта тема уже затронута.

Вот пример того, как обрабатывать фрагменты при регулярном изменении ориентации:

Активность :

public class MainActivity extends FragmentActivity {

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

        if (savedInstanceState == null) {
            TestFragment test = new TestFragment();
            test.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
        } else {
            TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
        }
    }
}

Фрагмент :

public class TestFragment extends Fragment {

    public static final String KEY_ITEM = "unique_key";
    public static final String KEY_INDEX = "index_key";
    private String mTime;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);

        if (savedInstanceState != null) {
            // Restore last state
            mTime = savedInstanceState.getString("time_key");
        } else {
            mTime = "" + Calendar.getInstance().getTimeInMillis();
        }

        TextView title = (TextView) view.findViewById(R.id.fragment_test);
        title.setText(mTime);

        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("time_key", mTime);
    }
}

спасибо Warpzit за ваши усилия, но я буду рад, если вы объясните в коде свою точку зрения. Как изменить мой код для обработки изменения ориентации без перезагрузки фрагмента.
user1811741 09

1
Следовательно, мне нужно, чтобы макет фрагмента был изменен при ориентации, но я не хочу перезагружать все записи, я сделал следующее: 1. добавить android: configchanges = "ориентация" в манифест 2. переопределить onConfigurationChanged во фрагменте и определить ориентацию и скрыть / показать список или сетку в зависимости от ориентации. Это правильный путь?
user1811741

@ user1811741 обновлен примером. Надеюсь, это все проясняет.
Warpzit

@Warpzit Как можно обработать тот же сценарий в случае реализации фрагмента ViewPager, поскольку ViewPager позаботится обо всех отображаемых фрагментах .. любое предложение.
CoDe

1
@Shubh хорошо, я считаю, что viewpager обрабатывает это правильно, если нет, вам придется переопределить реализацию getItem в соответствии с вашими потребностями. Надеюсь, это укажет вам правильное направление, если не задать правильный вопрос :)
Warpzit

21

Хорошее руководство о том, как сохранять данные между сменой ориентации и восстановлением активности, можно найти в рекомендациях для Android .

Резюме:

  1. сделайте свой фрагмент сохраняемым:

    setRetainInstance(true);
    
  2. Создавать новый фрагмент только в случае необходимости (или хотя бы брать из него данные)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
    

приятно Сохранить мое время вау
Арджун сайни
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.