조각은 UI 논리를 일부 모듈로 분리하는 데 매우 좋은 것 같습니다. 그러나 ViewPager
수명주기 와 함께 여전히 안개 낀다. 따라서 전문가의 생각이 절실히 필요합니다!
편집하다
아래 바보 같은 솔루션을 참조하십시오 ;-)
범위
주요 활동에는 ViewPager
조각이 있습니다. 이러한 조각은 다른 (서브) 활동에 대해 약간 다른 논리를 구현할 수 있으므로 조각의 데이터는 활동 내부의 콜백 인터페이스를 통해 채워집니다. 그리고 첫 출시에서 모든 것이 잘 작동하지만! ...
문제
액티비티가 다시 생성되면 (예 : 방향 변경 등) ViewPager
의 조각을 생성합니다. 코드 (아래에서 찾을 수 있음)는 활동이 생성 될 때마다 ViewPager
조각과 동일한 새 조각 어댑터 를 만들려고 시도 하지만 (문제 일 수도 있음) FragmentManager는 이미이 조각을 어딘가에 어디에 있습니까 (?) 이를위한 레크리에이션 메커니즘을 시작합니다. 따라서 레크리에이션 메커니즘은 Activity의 구현 된 메소드를 통해 데이터를 시작하기위한 콜백 인터페이스 호출과 함께 "오래된"프래그먼트의 onAttach, onCreateView 등을 호출합니다. 그러나이 메소드는 Activity의 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... */
}
해결책
바보 같은 해결책은 putFragment를 사용하여 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();
...
}