ViewPager и фрагменты - как правильно сохранить состояние фрагмента?
Фрагменты, кажется, очень хороши для разделения логики пользовательского интерфейса на некоторые модули. Но наряду сViewPager
его жизненный цикл все еще туманен для меня. Поэтому мысли Гуру крайне необходимы!
Смотрите тупое решение ниже ;-)
ОбъемОсновная деятельность имеетViewPager
с фрагментами. Эти фрагменты могут реализовывать несколько иную логику для других (подосновных) действий, поэтому данные фрагментов заполняются через интерфейс обратного вызова внутри действия. И все отлично работает при первом запуске, но! ...
Когда действие воссоздается (например, при изменении ориентации),ViewPager
фрагменты. Код (вы найдете ниже) говорит, что каждый раз, когда создается действие, я пытаюсь создать новыйViewPager
Адаптер фрагментов аналогичен фрагментам (возможно, это проблема), но FragmentManager уже хранит все эти фрагменты где-то (где?) и запускает механизм их восстановления. Таким образом, механизм восстановления вызывает «старый» фрагмент onAttach, onCreateView и т. Д. С моим вызовом интерфейса обратного вызова для инициирования данных через реализованный метод Activity. Но этот метод указывает на вновь созданный фрагмент, который создается с помощью метода onCreate в Activity.
Может быть, я использую неправильные шаблоны, но даже книга Android 3 Pro не так много об этом. Так,пожалуйстаДайте мне один-два удара и укажите, как это сделать правильно. Большое спасибо!
КодОсновное занятие
public class DashboardActivity extends BasePagerActivity implements OnMessageListActionListener {
private MessagesFragment mMessagesFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
Logger.d("Dash onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager_container);
new DefaultToolbar(this);
// create fragments to use
mMessagesFragment = new MessagesFragment();
mStreamsFragment = new StreamsFragment();
// set titles and fragments for view pager
Map<String, Fragment> screens = new LinkedHashMap<String, Fragment>();
screens.put(getApplicationContext().getString(R.string.dashboard_title_dumb), new DumbFragment());
screens.put(getApplicationContext().getString(R.string.dashboard_title_messages), mMessagesFragment);
// instantiate view pager via adapter
mPager = (ViewPager) findViewById(R.id.viewpager_pager);
mPagerAdapter = new BasePagerAdapter(screens, getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
// set title indicator
TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.viewpager_titles);
indicator.setViewPager(mPager, 1);
}
/* set of fragments callback interface implementations */
@Override
public void onMessageInitialisation() {
Logger.d("Dash onMessageInitialisation");
if (mMessagesFragment != null)
mMessagesFragment.loadLastMessages();
}
@Override
public void onMessageSelected(Message selectedMessage) {
Intent intent = new Intent(this, StreamActivity.class);
intent.putExtra(Message.class.getName(), selectedMessage);
startActivity(intent);
}
BasePagerActivity ака помощник
public class BasePagerActivity extends FragmentActivity {
BasePagerAdapter mPagerAdapter;
ViewPager mPager;
}
адаптер
public class BasePagerAdapter extends FragmentPagerAdapter implements TitleProvider {
private Map<String, Fragment> mScreens;
public BasePagerAdapter(Map<String, Fragment> screenMap, FragmentManager fm) {
super(fm);
this.mScreens = screenMap;
}
@Override
public Fragment getItem(int position) {
return mScreens.values().toArray(new Fragment[mScreens.size()])[position];
}
@Override
public int getCount() {
return mScreens.size();
}
@Override
public String getTitle(int position) {
return mScreens.keySet().toArray(new String[mScreens.size()])[position];
}
// hack. we don't want to destroy our fragments and re-initiate them after
@Override
public void destroyItem(View container, int position, Object object) {
// TODO Auto-generated method stub
}
}
Фрагмент
public class MessagesFragment extends ListFragment {
private boolean mIsLastMessages;
private List<Message> mMessagesList;
private MessageArrayAdapter mAdapter;
private LoadMessagesTask mLoadMessagesTask;
private OnMessageListActionListener mListener;
// define callback interface
public interface OnMessageListActionListener {
public void onMessageInitialisation();
public void onMessageSelected(Message selectedMessage);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// setting callback
mListener = (OnMessageListActionListener) activity;
mIsLastMessages = activity instanceof DashboardActivity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
inflater.inflate(R.layout.fragment_listview, container);
mProgressView = inflater.inflate(R.layout.listrow_progress, null);
mEmptyView = inflater.inflate(R.layout.fragment_nodata, null);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// instantiate loading task
mLoadMessagesTask = new LoadMessagesTask();
// instantiate list of messages
mMessagesList = new ArrayList<Message>();
mAdapter = new MessageArrayAdapter(getActivity(), mMessagesList);
setListAdapter(mAdapter);
}
@Override
public void onResume() {
mListener.onMessageInitialisation();
super.onResume();
}
public void onListItemClick(ListView l, View v, int position, long id) {
Message selectedMessage = (Message) getListAdapter().getItem(position);
mListener.onMessageSelected(selectedMessage);
super.onListItemClick(l, v, position, id);
}
/* public methods to load messages from host acitivity, etc... */
}
РешениеТупое решение состоит в том, чтобы сохранить фрагменты внутри onSaveInstanceState (хоста Activity) с помощью putFragment и получить их внутри onCreate через getFragment. Но у меня все еще есть странное чувство, что вещи не должны работать так ... Смотрите код ниже:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager()
.putFragment(outState, MessagesFragment.class.getName(), mMessagesFragment);
}
protected void onCreate(Bundle savedInstanceState) {
Logger.d("Dash onCreate");
super.onCreate(savedInstanceState);
...
// create fragments to use
if (savedInstanceState != null) {
mMessagesFragment = (MessagesFragment) getSupportFragmentManager().getFragment(
savedInstanceState, MessagesFragment.class.getName());
StreamsFragment.class.getName());
}
if (mMessagesFragment == null)
mMessagesFragment = new MessagesFragment();
...
}