Как сохранить состояние фрагмента без стопки в закладке?
Я пытаюсь сохранить состояние фрагмента в onSaveInstanceState
, но когда я возвращаюсь к фрагменту, он всегда перезагружается снова, а не начинается с последнего состояния.
Я просмотрел onCreateView
и onActivityCreated
и всегда имеет onSaveInstanceState
как null.
public void navigateFragment(String tag, Fragment fragment,
boolean shouldAdd) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (shouldAdd)
mStacks.get(tag).push(fragment); // push fragment on stack
ft.replace(android.R.id.tabcontent, fragment);
if (shouldAdd)
ft.addToBackStack(tag);
ft.commit();
}
Поскольку я не могу использовать backstack
, потому что в вкладках back stack не полезен. Любая помощь будет высоко оценена.
Ответы
Ответ 1
В этом случае вы должны сами управлять состояниями фрагментов. Я не знаю точно, как работает ваш код, поэтому единственное, что я могу сделать, это дать вам несколько советов.
Первое, что вам нужно реализовать, - сохранить состояние фрагмента. Предположим, что все фрагменты имеют уникальные идентификаторы. В этом случае вам нужно создать карту, которая будет содержать все состояния:
private final Map<String, Fragment.SavedState> mFragmentStates = new HashMap<>();
private void saveFragmentState(String id, Fragment fragment) {
Fragment.SavedState fragmentState =
getSupportFragmentManager().saveFragmentInstanceState(fragment);
mFragmentStates.put(id, fragmentState);
}
Вам нужно вызвать этот метод для фрагмента, который вы собираетесь удалить. Затем нам нужно восстановить состояние фрагмента и то, как мы можем это сделать:
private void restoreFragmentState(String id, Fragment fragment) {
Fragment.SavedState fragmentState = mFragmentStates.remove(id);
if (fragmentState != null) {
fragment.setInitialSavedState(savedState);
}
}
Этот метод необходимо вызвать перед добавлением фрагмента в транзакцию.
Предоставленный код должен работать нормально, но чтобы он корректно работал в режиме активного отдыха, нам необходимо правильно сохранить и восстановить mFragmentStates
:
private static final String KEY_FRAGMENT_STATES = "fragment_states";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Your code ... */
if (savedInstanceState != null) {
Bundle fragmentStates =
savedInstanceState.getParcelable(KEY_FRAGMENT_STATES);
if (fragmentStates != null) {
for (String id : fragmentStates.keySet()) {
Fragment.SavedState fragmentState =
fragmentStates.getParcelable(id);
mFragmentStates.put(id, fragmentState);
}
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/* Your code ... */
Bundle fragmentStates = new Bundle(mFragmentStates.size());
for (Map.Entry<String, Fragment.SavedState> entry : mFragmentStates.entrySet()) {
fragmentStates.put(entry.getKey(), entry.getValue());
}
outState.putParcelable(KEY_FRAGMENT_STATES, fragmentStates);
}
Также вы можете взглянуть на класс FragmentStatePagerAdapter. Он использует тот же подход для управления состояниями фрагментов ViewPager
.
UPDATE. И поэтому ваш код должен выглядеть примерно так:
private Fragment mCurrentFragment;
public void navigateFragment(String tag, Fragment fragment,
boolean shouldAdd) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
if (shouldAdd) {
mStacks.get(tag).push(fragment); // push fragment on stack
}
if (mCurrentFragment != null) {
saveFragmentState(mCurrentFragment.getClass().getName(), mCurrentFragment);
}
mCurrentFragment = fragment;
restoreFragmentState(fragment.getClass().getName(), fragment);
transaction.replace(android.R.id.tabcontent, fragment);
if (shouldAdd) {
// You shouldn't use back-stack when managing fragment states by yourself.
transaction.addToBackStack(tag);
}
transaction.commit();
}
В этом примере я использую имя класса фрагмента как id, поэтому весь фрагмент должен иметь разные классы. Но вы можете использовать любое другое уникальное значение как id. И еще одна важная вещь, которую я должен упомянуть, заключается в том, что вы не должны использовать back-stack при управлении состояниями фрагментов самостоятельно. Back-stack выполняет аналогичное управление состоянием, и у вас могут возникнуть конфликты.
Ответ 2
Я думаю, что вы должны использовать идею Общие предпочтения, это быстрее, чем использование локальных файлов или базы данных и, безусловно, проще кодировать. Хорошая веб-страница для Android @Параметры хранилища. Я приведу несколько примеров кода с веб-страницы и изменю несколько, чтобы удовлетворить ваши потребности.
Сначала получите данные, сохраненные из настроек в методе overCreate() override:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
...
}
Затем сохраните данные до того, как фрагмент остановится или выйдет по различным причинам. Достигните это путем переопределения метода onDetach
, вместо этого переопределите веб-страницу onStop()
.
@Override
public void onDetach() {
super.onDetach();
...
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// Commit the edits!
editor.commit();
}
Удачи, получайте удовольствие!
Ответ 3
Вы делаете заменяете фрагмент, вот почему фрагмент уничтожается. Вы можете попробовать ниже. Здесь я делаю две вещи в одном FragmentTransaction, я добавляет новый фрагмент и скрывает существующий фрагмент.
Предположим, что мы добавляем фрагмент B поверх фрагмента A
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.add(android.R.id.tabcontent, fragmentB, tagFragmentB)
.hide(fragmentManager.findFragmentByTag(tagFragmentA))
.addToBackStack(tag)
.commit();
После того, как вы вернетесь, он будет удалить фрагмент B и показать фрагмент A с тем же (прежде чем добавить фрагмент B)
Обратите внимание: tagFragmentA и tagFragmentB - это теги, в которые добавляются фрагменты A и B соответственно p >
Ответ 4
Я не понимаю, какой вид вы используете для реализации вкладок.
Я догадался,
ft.replace(android.R.id.tabcontent, fragment);
что вы, возможно, внедрили FragmentTabHost.
напишите customFragmentTabhost и переопределите
@Override
public void onTabChanged(String tabId) {
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
if (tabId.equals("Tab1")) {
TabFragment1 fragment1 = null;
if (getSupportFragmentManager().findFragmentByTag("Tab1") == null) {
fragment1 = new TabFragment1();
} else {
fragment1 = (TabFragment1) getSupportFragmentManager().findFragmentByTag("Tab1");
}
t.replace(R.id.realContent, fragment1, "Tab1").addToBackStack(null).commit();
}
}
UPDATE:
-
Убедитесь, что активность не воссоздана по ориентации, если установлено setRetainInstance (true), так что даже если активность будет воссоздана при изменении ориентации, фрагменты будут сохранены.
-
Предоставлять id для любых видов в фрагменте. Для системы Android важно поддерживать состояние.
Ответ 5
clearBackStackEntry();
rl.setVisibility(View.GONE);
getSupportFragmentManager().beginTransaction()
.replace(FRAGMENT_CONTAINER, new HomeScreen())
.addToBackStack(null).commit();
private void clearBackStackEntry() {
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count > 0) {
getSupportFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
TRY THIS AND One more for fragment also try this: but use support.v4.app.Fragment, May be it will help you
Fragment fr = new main();
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.commit();
// getActivity().finish();
Ответ 6
объявить
setRetainInstance(true)
В вашем фрагменте onCreate(). воссоздать предыдущее состояние
И ссылка будет полезна для понимания того, как работает setRetainInstance.
Общие сведения о наборе фрагментовRetainInstance (boolean)
Зачем использовать Fragment # setRetainInstance (boolean)?
Спасибо:)
Ответ 7
очень просто справиться с этими вещами. Я могу дать вам образец для обработки обратного нажатия на агенты Fr, которые мы добавили.
Я объявил стек фрагментов и нажимаю на него все фрагменты:
public static Stack<Fragment> fragmentStack;
создайте такой метод:
public static void replaceFragementsClick(Fragment fragementObj, Bundle bundleObj, String title){
try {
FragmentManager fragmentManager = ((FragmentActivity) mContext).getSupportFragmentManager();
if (fragementObj != null) {
fragementObj.setArguments(bundleObj);
fragmentManager.beginTransaction().replace(R.id.frame_container, fragementObj).commit();
}
DashBoardActivity.fragmentStack.push(fragementObj);
} catch (Exception e) {
e.printStackTrace();
}
}
Попробуйте также:
public static void replaceFragementsClickBack(Fragment fragementObj, Bundle bundleObj, String title){
try {
FragmentManager fragmentManager = ((FragmentActivity) mContext).getSupportFragmentManager();
if (fragementObj != null) {
fragementObj.setArguments(bundleObj);
fragmentManager.beginTransaction().replace(R.id.frame_container, fragementObj).commit();
DashBoardActivity.fragmentStack.pop();
}
} catch (Exception e) {
e.printStackTrace();
}
}
В базовом активном действии, в котором вы добавили, отмените подавление, например:
@Override
public void onBackPressed() {
/**
* Do Current Fragment Pop
* */
fragmentStack.pop();
if(fragmentStack.size() >0){
Bundle bunldeObj = new Bundle();
//******Exit from Current Fragment
Fragment fragment = fragmentStack.pop();
// fragmentStack.push(fragment);
if(fragment instanceof PhotosFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Photos");
}else if(fragment instanceof PhotoDetatilFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Photos");
}else if(fragment instanceof PhotoFullViewFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Photos");
}else if(fragment instanceof HomeFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Home");
}else if(fragment instanceof VideosFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Videos");
}else if(fragment instanceof VideoDetailFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Videos");
}else if(fragment instanceof VideoViewFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Videos");
}else if(fragment instanceof MusicFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Music");
}else if(fragment instanceof MusicListFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Music");
}else if(fragment instanceof InstallAppsFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Apps");
}else if(fragment instanceof MessageFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Messages");
}else if(fragment instanceof MessageDetailFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Messages");
}else if(fragment instanceof LocateDeviceFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Locate Device");
}else if(fragment instanceof FilesFragmentBottomBar){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Files");
}else if(fragment instanceof AppsFragment){
bunldeObj.putString("position", "4");
replaceFragementsClick(fragment,bunldeObj,"Apps");
}else {
super.onBackPressed();
Intent intent = new Intent(DashBoardActivity.this,ConnectDeviceActivity.class);
startActivity(intent);
finish();
}
}