[解決済み] FragmentPagerAdapterが古いフラグメントへの参照を保持するサポート
質問
私の問題は、FragmentManager が古いフラグメントのインスタンスを保持することと、ビューページャーが FragmentManager と同期していないことの問題であると絞り込まれました。この問題を参照してください。 http://code.google.com/p/android/issues/detail?id=19211#makechanges . 私はまだこれを解決する方法の手がかりを持っていません。何か提案はありますか?
私は長い間これをデバッグしようとしましたが、どんな助けでも非常に感謝されます。私は FragmentPagerAdapter を使用しており、このアダプタはこのようにフラグメントのリストを受け取ります。
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, Fragment1.class.getName()));
...
new PagerAdapter(getSupportFragmentManager(), fragments);
実装は標準的なものです。ActionBarSherlockとFragmentsのv4計算可能性ライブラリを使っています。
私の問題は、アプリを終了し、他のアプリケーションをいくつか開いて戻ってくると、フラグメントが FragmentActivity への参照を失うことです。
getActivity() == null
). なぜこのようなことが起こるのかがわかりません。私は、手動で
setRetainInstance(true);
を手動で設定しようとしましたが、これは役に立ちません。FragmentActivityが破壊されたときに発生すると考えましたが、ログメッセージが表示される前にアプリを開くと、まだこの現象が発生しています。何かアイデアはありますか?
@Override
protected void onDestroy(){
Log.w(TAG, "DESTROYDESTROYDESTROYDESTROYDESTROYDESTROYDESTROY");
super.onDestroy();
}
アダプタのことです。
public class PagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
@Override
public int getCount() {
return this.fragments.size();
}
}
フラグメントの1つが剥がれましたが、剥がれた部分を全てコメントアウトしても、まだ動きません。
public class MyFragment extends Fragment implements MyFragmentInterface, OnScrollListener {
...
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
handler = new Handler();
setHasOptionsMenu(true);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.w(TAG,"ATTACHATTACHATTACHATTACHATTACH");
context = activity;
if(context== null){
Log.e("IS NULL", "NULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULL");
}else{
Log.d("IS NOT NULL", "NOTNOTNOTNOTNOTNOTNOTNOT");
}
}
@Override
public void onActivityCreated(Bundle savedState) {
super.onActivityCreated(savedState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.my_fragment,container, false);
return v;
}
@Override
public void onResume(){
super.onResume();
}
private void callService(){
// do not call another service is already running
if(startLoad || !canSet) return;
// set flag
startLoad = true;
canSet = false;
// show the bottom spinner
addFooter();
Intent intent = new Intent(context, MyService.class);
intent.putExtra(MyService.STATUS_RECEIVER, resultReceiver);
context.startService(intent);
}
private ResultReceiver resultReceiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, final Bundle resultData) {
boolean isSet = false;
if(resultData!=null)
if(resultData.containsKey(MyService.STATUS_FINISHED_GET)){
if(resultData.getBoolean(MyService.STATUS_FINISHED_GET)){
removeFooter();
startLoad = false;
isSet = true;
}
}
switch(resultCode){
case MyService.STATUS_FINISHED:
stopSpinning();
break;
case SyncService.STATUS_RUNNING:
break;
case SyncService.STATUS_ERROR:
break;
}
}
};
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.activity, menu);
}
@Override
public void onPause(){
super.onPause();
}
public void onScroll(AbsListView arg0, int firstVisible, int visibleCount, int totalCount) {
boolean loadMore = /* maybe add a padding */
firstVisible + visibleCount >= totalCount;
boolean away = firstVisible+ visibleCount <= totalCount - visibleCount;
if(away){
// startLoad can now be set again
canSet = true;
}
if(loadMore)
}
public void onScrollStateChanged(AbsListView arg0, int state) {
switch(state){
case OnScrollListener.SCROLL_STATE_FLING:
adapter.setLoad(false);
lastState = OnScrollListener.SCROLL_STATE_FLING;
break;
case OnScrollListener.SCROLL_STATE_IDLE:
adapter.setLoad(true);
if(lastState == SCROLL_STATE_FLING){
// load the images on screen
}
lastState = OnScrollListener.SCROLL_STATE_IDLE;
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
adapter.setLoad(true);
if(lastState == SCROLL_STATE_FLING){
// load the images on screen
}
lastState = OnScrollListener.SCROLL_STATE_TOUCH_SCROLL;
break;
}
}
@Override
public void onDetach(){
super.onDetach();
if(this.adapter!=null)
this.adapter.clearContext();
Log.w(TAG, "DETACHEDDETACHEDDETACHEDDETACHEDDETACHEDDETACHED");
}
public void update(final int id, String name) {
if(name!=null){
getActivity().getSupportActionBar().setTitle(name);
}
}
}
updateメソッドは、ユーザーが別のフラグメントと対話し、getActivityがnullを返しているときに呼び出されます。以下は、別のフラグメントが呼び出しているメソッドです。
((MyFragment) pagerAdapter.getItem(1)).update(id, name);
アプリを破棄して再度作成すると、デフォルトのフラグメントにアプリを起動するのではなく、アプリが起動し、viewpager が最後の既知のページにナビゲートするのだと思います。これは奇妙に思えますが、アプリはデフォルトのフラグメントにロードされるべきではないでしょうか?
どのように解決するのですか?
の外側でフラグメントをインスタンス化し、その参照を保持しているため、問題に遭遇しています。
PagerAdapter.getItem
の外側でフラグメントへの参照をインスタンス化して保持し、それらの参照をViewPagerから独立して使用しようとしているためです。Seraphが言うように、あるフラグメントが特定の時間にViewPagerでインスタンス化/追加されたことを保証する必要があります。ViewPagerは、そのページの遅延ロードを行います。デフォルトでは、現在のページと、左右のページのみをロードします。
アプリをバックグラウンドにした場合、フラグメントマネージャーに追加されたフラグメントは、自動的に保存されます。アプリを終了しても、アプリを再起動すると、この情報は復元されます。
フラグメントマネージャに追加されたフラグメントA、B、Cのページを閲覧したとします。なぜなら、あなたは
FragmentPagerAdapter
ではなく
FragmentStatePagerAdapter
でない場合、これらのフラグメントは他のページにスクロールしたときに追加されます(ただし、切り離される可能性があります)。
その後、アプリケーションをバックグラウンドにし、それが強制終了された場合を考えてみましょう。戻ってきたとき、Android はフラグメント マネージャーにフラグメント A、B、および C があったことを覚えているので、それらを再作成し、追加します。 しかし、フラグメントマネージャーに追加されたフラグメントは、アクティビティーのフラグメントリストにあるものではありません。
FragmentPagerAdapter は、フラグメントマネージャを呼び出すために
getPosition
を呼び出そうとしません。実際、Android によって再作成されたフラグメントは決して削除されないので、それを
getPosition
. また、未知のタグで追加されているため、その参照を取得することもかなり困難です。これは意図的なもので、ビューページャーが管理しているフラグメントをいじらないようにするためです。フラグメント内ですべてのアクションを実行し、アクティビティと通信し、必要であれば、特定のページに切り替えるよう要求すべきです。
さて、行方不明のアクティビティに関する問題に戻ります。呼び出し
pagerAdapter.getItem(1)).update(id, name)
を実行した後、リストにあるフラグメントを返します。
を返しますが、これはまだフラグメントマネージャに追加されていません。
で、Activityの参照はありません。私は、あなたの更新メソッドは、いくつかの共有データ構造(おそらくアクティビティによって管理される)を変更する必要があり、その後、特定のページに移動すると、この更新されたデータに基づいて自分自身を描画することができます示唆していると思います。
関連
-
[解決済み] なぜフラグメントなのか、そしてアクティビティの代わりにフラグメントを使用するのはどんなときか?
-
[解決済み] フラグメントのインスタンス状態をバックスタックに正しく保存する方法は?
-
[解決済み] プログラム的に電話をかけるには?
-
[解決済み] Android - タイトルバーに戻るボタンが表示される
-
[解決済み] Android Studio - あいまいなメソッド呼び出し getClass()
-
[解決済み] データベースでリサイクルビューを使用する
-
[解決済み] Gmailの3分割アニメーションシナリオの完全動作サンプル?
-
[解決済み] onCreate(Bundle savedInstanceState)とは?
-
[解決済み] 非推奨のandroid.support.v4.app.ActionBarDrawerToggleの置き換え方法
-
[解決済み] <string> XMLで改行やタブを作るには(eclipse/android)?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Android. Fragment getActivity()がNULLを返すことがある
-
[解決済み] Android Webview - キャッシュを完全に削除する
-
[解決済み] Androidのソースコードにある@hideの意味とは?
-
[解決済み] wrap_contentでRelativeLayoutがフルスクリーンになってしまう
-
[解決済み] onCreate(Bundle savedInstanceState)とは?
-
[解決済み] EditTextをReadOnlyにする
-
[解決済み] edittextのテキストがメールアドレスかどうかを確認するには?
-
[解決済み] アダプタからActivityメソッドを呼び出す
-
[解決済み] WhatsAppでメッセージを送信する
-
[解決済み] FragmentPagerAdapterを使用した場合の既存のフラグメントの取得方法