Fragmenty wydają się bardzo przydatne do rozdzielenia logiki interfejsu użytkownika na niektóre moduły. Ale wraz z ViewPager
cyklem życia nadal jest dla mnie mglisty. Więc myśli Guru są bardzo potrzebne!
Edytować
Zobacz głupie rozwiązanie poniżej ;-)
Zakres
Główna działalność ma ViewPager
fragmentami. Fragmenty te mogą implementować nieco inną logikę dla innych (podrzędnych) działań, więc dane fragmentów są wypełniane przez interfejs wywołania zwrotnego wewnątrz działania. I wszystko działa dobrze przy pierwszym uruchomieniu, ale! ...
Problem
Kiedy aktywność zostanie odtworzona (np. Przy zmianie orientacji), wykonaj również ViewPager
fragmenty. Kod (znajdziesz poniżej) mówi, że za każdym razem, gdy działanie jest tworzone, próbuję utworzyć nowy ViewPager
adapter fragmentów, taki sam jak fragmenty (może to jest problem), ale FragmentManager już ma wszystkie te fragmenty gdzieś (gdzie?) I uruchamia dla nich mechanizm rekreacji. Tak więc mechanizm odtwarzania wywołuje „stary” fragment onAttach, onCreateView itp. Z moim wywołaniem interfejsu zwrotnego do inicjowania danych za pomocą zaimplementowanej metody działania. Ale ta metoda wskazuje na nowo utworzony fragment, który jest tworzony za pomocą metody onCreate działania.
Kwestia
Może używam niewłaściwych wzorów, ale nawet książka na Androida 3 Pro nie ma o tym wiele. Więc proszę , daj mi jeden-dwa uderzenie i wskaż, jak to zrobić we właściwy sposób. Wielkie dzięki!
Kod
Główna aktywność
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 aka pomocnik
public class BasePagerActivity extends FragmentActivity {
BasePagerAdapter mPagerAdapter;
ViewPager mPager;
}
Adapter
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
}
}
Fragment
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... */
}
Rozwiązanie
Głupim rozwiązaniem jest zapisanie fragmentów wewnątrz onSaveInstanceState (działania hosta) za pomocą putFragment i umieszczenie ich w środku onCreate poprzez getFragment. Ale nadal mam dziwne przeczucie, że rzeczy nie powinny tak działać ... Zobacz poniższy kod:
@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();
...
}