1

У меня есть экран, на котором пользователь нажимает кнопку, чтобы вызвать DialogFragment с EditText. Они вводят свою информацию и нажимают Ok. Если они снова нажмут кнопку, я сделал так, чтобы EditText отображал информацию, которую они только что положили, и все работает нормально.Сохранение информации из одного фрагмента и диалога, если пользователь переходит к другому фрагменту

Однако, если ввести информацию, нажмите Ok, а затем с помощью меню опций, чтобы пойти посмотреть на другой экран/fragment, информация не будет отображаться в EditText, когда они снова нажмите на кнопку.

Как сохранить информацию, даже если пользователь на некоторое время переходит от этого экрана? Я думаю, для этого потребуется метод newInstance в классе фрагментов, а затем вместо него будет иметь хост-активность newInstance. Но я не уверен, как его реализовать. Любая помощь оценивается. Благодаря!

SingleFragmentActivity:

public abstract class SingleFragmentActivity extends FragmentActivity 
{ 
    protected abstract Fragment createFragment(); 

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

     FragmentManager fm = getSupportFragmentManager(); 
     Fragment fragment = fm.findFragmentById(R.id.fragmentContainer); 

     if (fragment == null) 
     { 
      fragment = createFragment(); 
      fm.beginTransaction() 
       .add(R.id.fragmentContainer, fragment) 
       .commit(); 
     } 
    } 
} 

Соответствующий код от хостинговой деятельности, AdviceActivity:

public class AdviceActivity extends SingleFragmentActivity 
{ 
    @Override 
    protected Fragment createFragment() 
    { 
     return new AdviceFragment(); 
    } 
} 

Соответствующий код от принимающего фрагмента, AdviceFragment:

private boolean isTextButtonFirstClick = true; 

... 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) 
{ 
    mTextButton = (Button) v.findViewById(R.id.textButton); 
    mTextButton.setOnClickListener(new View.OnClickListener() 
    { 
     public void onClick(View v) 
     { 
      if (isTextButtonFirstClick) 
      { 
       FragmentManager fm = getActivity().getSupportFragmentManager(); 
       InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick); 
       dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT); 
       dialog.show(fm, DIALOG_TEXT); 
       isTextButtonFirstClick = false; 
      } 
      else 
      { 
       FragmentManager fm = getActivity().getSupportFragmentManager(); 
       InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick); 
       dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT); 
       dialog.show(fm, DIALOG_TEXT); 
      } 
     } 
    }); 
... 
} 

Соответствующий код из DialogFragment InputTextFragment:

public static InputTextFragment newInstance(String text, boolean isTextButtonFirstClick) 
{ 
    Bundle args = new Bundle(); 
    args.putSerializable(EXTRA_TEXTBUTTON_FIRSTCLICK, isTextButtonFirstClick); 
    args.putSerializable(EXTRA_TEXT, text); 

    InputTextFragment fragment = new InputTextFragment(); 
    fragment.setArguments(args); 

    return fragment; 
} 

... 

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) 
{ 
    ... 

    boolean isTextButtonFirstClick = getArguments().getBoolean(EXTRA_TEXTBUTTON_FIRSTCLICK); 

    final EditText editText = (EditText) v.findViewById(R.id.dialogInputEditText); 
    if (!isTextButtonFirstClick) 
    { 
     editText.setText(text); 
     editText.setSelection(text.length()); 
    } 

    ... 
} 

XML activity_fragment:

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

</RelativeLayout> 

ответ

1

Это звучит так, как если логическое isTextButtonFirstClick просто ошибочно установлен в ложь.

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

Попробуйте

  • Установка setRetainInstance (истина) в OnCreate совет Фрагмент для того, чтобы сохранить логическое значение.

  • Если R.id.fragmentContainer фрагмент тега в XML, а затем изменить его на LinearLayout или RelativeLayout (вы добавляете фрагмент сверху в любом случае, и я подозреваю, что findFragmentById всегда возвращает нуль)

  • Изменения кода в деятельности по:

    FragmentManager fm = getSupportFragmentManager(); 
    Fragment fragment = fm.findFragmentByTag("singleFragment"); 
    
    if (fragment == null) 
    { 
        fragment = createFragment(); 
    } 
    
        fm.beginTransaction() 
         .replace(R.id.fragmentContainer, fragment, "singleFragment") 
         .commit(); 
    

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

Похоже, что вы находитесь в промежуточном решении, пытаясь сделать то и другое, что не будет работать должным образом.

Надеюсь, что это может помочь и извинить заранее, если есть проблемы с форматированием.Ответ был написан с телефона :-)

Edit:

Если вы только хотели сохранить простые типы информации (такие, как логическое значение), я хотел бы указать вам на один из моих старых ответов здесь: Saving textview in a fragment when rotating screen

Ваш последний комментарий показал, что у вас есть сложная информация (текст, фотографии, видео и т. д.), которые вы хотите сохранить.

делая все, что Parcelable будет огромная боль, так что здесь идет мой второй совет:

  1. Добавить EventBus в свой проект https://github.com/greenrobot/EventBus
  2. Создать класс держатель для информации, такие как

    public class AdviceHolder { 
        private boolean isTextButtonFirstClick; 
        private String text; 
        private BitMap image; 
        ... 
    
        // setter and getter methods (if using eclipse alt+shit+s 'create setter and getters from fields') 
    } 
    
  3. Теперь при запуске AdviceActivity, вы готовите новый AdviceHolder

    public class AdviceActivity extends SingleFragmentActivity 
    { 
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
         // make a new AdviceHolder if none existed 
         AdviceHolder holder = new AdviceHolder(); 
         AdviceHolder existingHolder = EventBus.getDefault().getStickyEvent(AdviceHolder.class); 
         if (existingHolder == null) {   
          EventBus.getDefault().postSticky(holder); 
         } 
    
         super.onCreate(savedInstanceState); 
        } 
    
        @Override 
        protected Fragment createFragment() 
        { 
         return new AdviceFragment(); 
        } 
    } 
    

Этого шаг сделает объект AdviceHolder доступен в любом месте в вашем коде. Подумайте об этом как о глобальном хранилище.

Это означает, что независимо от того, как вы переходите между Activites или Fragments, все они имеют доступ к AdviceHolder и могут редактировать его.

Так, например, в вас AdviceFragment:

private AdviceHolder holder; 

... 
@Override 
public void onCreate (Bundle savedInstanceState) { 
    AdviceHolder holder = (AdviceHolder)EventBus.getDefault().getStickyEvent(AdviceHolder.class); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) 
{ 
    // read isTextButtonFirstClick from holder 
    boolean isTextButtonFirstClick = holder.isTextButtonFirstClick(); 

    mTextButton = (Button) v.findViewById(R.id.textButton); 
    mTextButton.setOnClickListener(new View.OnClickListener() 
    { 
     public void onClick(View v) 
     { 
      if (isTextButtonFirstClick) 
      { 
       FragmentManager fm = getActivity().getSupportFragmentManager(); 
       InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick); 
       dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT); 
       dialog.show(fm, DIALOG_TEXT); 

       // update isTextButtonFirstClick in holder 
       holder.setTextButtonFirstClick(false); 
       EventBus.getDefault().postStickyEvent(holder); 
      } 
      else 
      { 
       FragmentManager fm = getActivity().getSupportFragmentManager(); 
       InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick); 
       dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT); 
       dialog.show(fm, DIALOG_TEXT); 
      } 
     } 
    }); 
... 
} 

Когда вы в какой-то момент делается заполнение AdviceHolder (и отправил его на сервер или любой другой план есть), удалите его из EventBus для того, чтобы создать нового владельца в AdviceActivity.

EventBus.getDefault().removeStickyEvent(AdviceHolder.class); 

Для других примеров о EventBus взглянуть на http://www.stevenmarkford.com/passing-objects-between-android-activities/

Это все много информации, надеюсь, что это не слишком запутанной.

+0

Благодарим за ответ! Когда вы говорите, чтобы изменить код в 'Activity', вы имеете в виду изменить код в' AdviceActivity' или 'SingleFragmentActivity'? Я очень новичок в Android, поэтому не уверен. Другие фрагменты Действия также расширяют «SingleFragmentActivity». – pez

+1

Без проблем :) Я имел в виду SingleFragmentActivity. Если эти шаги не работают, я бы хотел, чтобы вы делили XML-файл «R.layout.activity_fragment». – cYrixmorten

+0

Спасибо. Прошлой ночью я обновил SingleFragmentActivity с вашим кодом, но Android Studio показала ошибку, заявив, что ожидается интерфейс или класс, я думаю. Вместо этого я сделал AdviceActivity расширением FragmentActivity и реализовал там свой код, и, хотя у него нет ошибок, проблема все же возникла. Я поделюсь XML, как только вернусь домой с работы сегодня, и я еще раз прокомментирую, чтобы обновить вас. Еще раз спасибо за помощь – pez