8

フラグメントを復元しようとすると、Androidアプリがクラッシュするという問題があります。復元しようとしているバンドルにカスタム変数を追加していません。すべてデフォルトです。FragmentsとViewPagerを使用しています。以下の私のコードスニペットを参照してください。

public static class MyAdapter extends FragmentStatePagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    public int getCurrentItemPosition(Fragment fragment){
        return getItemPosition(fragment);
    }

    @Override
    public Fragment getItem(int position) {
        return ContentFragment.newInstance(position);
    }
}

public class MyActivity extends FragmentActivity {

static final int NUM_ITEMS = 100000;
public int currentSelectedPage;
private int changeToFragmentIndex;
public DateTime midDate;
MyAdapter mAdapter;
ViewPager mPager;

/** Called when the activity is first created. */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.diary);
    MyApplication application = (MyApplication)getApplication();
    application.dataController.myActivity = this;
    mAdapter = new MyAdapter(getSupportFragmentManager());
    mPager = (ViewPager)findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);
    int newDay = application.daysBetween(DateTime.now(), DateTime.parse(application.day.dateToShortString()));

    this.currentSelectedPage = NUM_ITEMS/2+newDay;
    mPager.setCurrentItem(NUM_ITEMS/2+newDay);
    mPager.setOnPageChangeListener(new SimpleOnPageChangeListener(){
        public void onPageSelected(int position){
            currentSelectedPage = position;
            ContentFragment fragment = (ContentFragment) mAdapter.instantiateItem(mPager, currentSelectedPage);
            fragment.loadData();
        }
    });
}

}

public class ContentFragment extends Fragment {
private View v;
static final int NUM_ITEMS = 100000;

static ContentFragment newInstance(int num) {
    ContentFragment f = new ContentFragment();

    return f;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    if (container == null)
        return null;
    v = inflater.inflate(R.layout.diarycontent, container, false);
    return v;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

}

@Override
public void onSaveInstanceState(Bundle savedInstanceState){
    super.onSaveInstanceState(savedInstanceState);
    setUserVisibleHint(true);
}
}

私はこのstackstraceを受け取ります:

Caused by: java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:519)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:1 55)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:522)

私が理解したように、これはサポートパッケージの既知の問題であり、考えられる解決策の1つは、onSaveInstanceStateでsetUserVisibleHint(true)を使用することです。しかし、それは役に立ちませんでした。

誰かが問題の別の解決策や私が間違ったことを知っていますか?

4

3 に答える 3

25

Tab 内で FragmentStatePagerAdapter を使用して ViewPager を使用し始めると、同じタイプの問題に直面しました。

次に、この問題に関連するすべてのフォーラムで遊んで、この問題が発生した理由と解決方法を見つけるために 2 日間頭を悩ませましたが、私の要件を満たす完璧な解決策は見つかりませんでした。

FragmentStatePagerAdapter の代わりに FragmentPagerAdapter を使用して NPE クラッシュを回避するための解決策を得ました。FragmentStatePagerAdapter の代わりに FragmentPagerAdapter を置き換えると、NPE のクラッシュの問題に直面することはありませんが、同じページがさらにナビゲーションのために更新されません (これが私の要件です)。

最後に FragmentStatePagerAdapter の saveState メソッドをオーバーライドすると、すべてが正常に機能します。

@Override
public Parcelable saveState() {
    // Do Nothing
    return null;
}


この問題を簡単に再現する方法:
より高いバージョン (4.1) のデバイスを使用しており、以下の手順に従っています:
1. [設定] -> [開発者向けオプション] に移動します。
2. [アクティビティを保持しない] オプションをクリックします。

今、私は自分のアプリで遊んだ。

android.support.v4.app.FragmentManagerImpl.getFragment(Unknown Source) の NPE が原因でアプリがクラッシュするたびに saveState() メソッドをオーバーライドする前に。しかし、 saveState() をオーバーライドした後、クラッシュは登録されません。

そうすることで、問題が発生しないことを願っています。

于 2013-03-16T02:32:30.320 に答える
2

私は最初に@Lalit Kumar Sahooによって提案されたソリューションを使用しました。ただし、重大な問題に気付きました。デバイスをローテーションするたびに、Fragment Manager は古いフラグメントを削除せずに新しいフラグメントを追加しました。そこで、さらに検索したところ、回避策の提案が記載されたバグ レポートが見つかりました (投稿 #1 )。この修正を使用してアプリでテストしたところ、問題は副作用なしで解決されたようです。

回避策:プロジェクトの src/android/support/v4/app フォルダーにカスタム FragmentStatePagerAdapter を作成して使用します。

package android.support.v4.app;

import android.os.Bundle;
import android.view.ViewGroup;

public abstract class FixedFragmentStatePagerAdapter extends FragmentStatePagerAdapter {

  public FixedFragmentStatePagerAdapter(FragmentManager fm) {
    super(fm);
  }

  @Override
  public Object instantiateItem(ViewGroup container, int position) {
    Fragment f = (Fragment)super.instantiateItem(container, position);
    Bundle savedFragmentState = f.mSavedFragmentState;
    if (savedFragmentState != null) {
      savedFragmentState.setClassLoader(f.getClass().getClassLoader());
    }
    return f;
  }
}
于 2013-10-15T09:13:07.483 に答える
-1

なぜあなたは正確にやっているのですか:

mPager.setOnPageChangeListener(new SimpleOnPageChangeListener(){
    public void onPageSelected(int position){
        currentSelectedPage = position;
        ContentFragment fragment = (ContentFragment) mAdapter.instantiateItem(mPager, currentSelectedPage);
        fragment.loadData();
    }
});

これ:

@Override
public Fragment getItem(int position) {
    return ContentFragment.newInstance(position);
}

フラグメントをインスタンス化します。

次のようなデータをフラグメントにロードできます。

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadData();
}
于 2012-06-19T20:38:06.917 に答える