フラグメントは、UIロジックをいくつかのモジュールに分離するのに非常に適しているようです。しかし、ViewPager
そのライフサイクルとともに、私にはまだ霧がかかっています。だからグルの考えはひどく必要です!
編集する
以下のばかげた解決策を参照してください;-)
範囲
メインアクティビティにはViewPager
フラグメントがあります。これらのフラグメントは、他の(サブメイン)アクティビティに対して少し異なるロジックを実装できるため、フラグメントのデータはアクティビティ内のコールバックインターフェイスを介して入力されます。そして、すべては最初の起動で正常に動作しますが、!...
問題
アクティビティが再作成されたとき(たとえば、方向が変更されたとき)ViewPager
のフラグメントを作成します。コード(以下にあります)は、アクティビティが作成されるたびに、ViewPager
フラグメントと同じ新しいフラグメントアダプターを作成しようとする(多分これが問題である)と述べていますが、FragmentManagerはすでにこれらのフラグメントをどこかに(どこに?)格納しています。それらのレクリエーションメカニズムを開始します。したがって、レクリエーションメカニズムは、アクティビティの実装されたメソッドを介してデータを開始するためのコールバックインターフェース呼び出しで「古い」フラグメントのonAttach、onCreateViewなどを呼び出します。ただし、このメソッドは、アクティビティのonCreateメソッドで作成された、新しく作成されたフラグメントを指します。
問題
多分私は間違ったパターンを使用していますが、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内にフラグメントを保存し、getFragmentを介してonCreate内に取得することです。しかし、私はまだそれがそのように機能するべきではないという奇妙な気持ちを持っています...以下のコードを参照してください:
@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();
...
}