1

私のアプリケーションには、MainActivityに2つのフラグメントを持つViewPagerが含まれています。最初のフラグメントにはListViewが含まれています。これは表示されませんが、GooglePlayのRuntimeExceptionに関するユーザーからのレポートが表示されます。

java.lang.RuntimeException: Unable to resume activity {com.my.project/com.my.project.MainActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {com.my.project/com.my.project.MainActivity}: java.lang.NullPointerException
 at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120)
 at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668)
 at android.app.ActivityThread.access$1500(ActivityThread.java:117)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
 at android.os.Handler.dispatchMessage(Handler.java:99)
 at android.os.Looper.loop(Looper.java:130)
 at android.app.ActivityThread.main(ActivityThread.java:3683)
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:507)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:875)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:633)
 at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {com.my.project/com.my.project.MainActivity}: java.lang.NullPointerException
 at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
 at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2107)
 ... 12 more
Caused by: java.lang.NullPointerException
 at com.my.project.FirstFragment.load(FirstFragment.java:551)
 at com.my.project.MainActivity.onActivityResult(MainActivity.java:132)
 at android.app.Activity.dispatchActivityResult(Activity.java:3908)
 at android.app.ActivityThread.deliverResults(ActivityThread.java:2528)
 ... 13 more

FirstFragment.javaのコードは次のとおりです。

public class FirstFragment extends Fragment {

    ArrayList<ListItemObject> listItems = null;
    ArrayAdapter<ListItemObject> mAdapter;

    void load() {
            mAdapter.clear(); // I get error here, that is FirstFragment.java:551
            ...
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        listItems = new ArrayList<ListItemObject>();
        mAdapter = new MyAdapter(getActivity(), listItems);
        listView.setAdapter(mAdapter);
    }

}

それがmAdapterのすべての出来事です。そして、それがどのようにしてNullPointerExceptionを引き起こすのか理解できません。Fragment1が破棄して再作成することもあると思いますが、onCreateView()はありません。この問題を抱えているユーザーの1人と話をしたところ、設定の[開発者向けオプション]で[アクティビティを保持しない]をオフにすると、このバグが発生したとのことです。わかりませんが、修正できますか?または、すべてのユーザーに「このオプションのチェックを外す」と言う必要がありますか?

私のNainActivityで:

public class MainActivity extends FragmentActivity {

    Vector<Fragment> fragments;
    ViewPager viewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        viewPager = (ViewPager) findViewById(R.id.pager);

        fragments = new Vector<Fragment>();
        fragments.add(Fragment.instantiate(this, Fragment1.class.getName()));
        fragments.add(Fragment.instantiate(this, Fragment2.class.getName()));

        viewPager.setOffscreenPageLimit(fragments.size());
        PagerAdapter pagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);

        viewPager.setAdapter(pagerAdapter);

        viewPager.setCurrentItem(0);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==1) {
            ((MainChat)fragments.get(0)).load();
        }
    }

    class PagerAdapter extends FragmentPagerAdapter implements IconPagerAdapter {

        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();
        }

    }

}
4

2 に答える 2

0

エラーの理由は、 MainActivity が破棄され、Android OS によって再作成されたためだと思います。

つまり、MainActivity.onCreate() メソッドでフラグメント リストが再度作成されますが、PagerAdapter はそれらのフラグメントを使用せず、代わりに FragmentManager によって復元されたフラグメントのインスタンスを使用します (たとえば、PagerAdapter.getItem() は呼び出されません)。 )。また、フラグメント リストの FirstFragment のインスタンスは使用されないため、FirstFragment.onCreateView() への呼び出しを受信せず、mAdapter インスタンスは null のままで、FirstFragment.load() メソッドを呼び出します。

この問題を修正する最も簡単な (しかしあまり良い方法ではありません) 方法は、MainActivity.onCreate() でsavedInstanceState パラメータとして null を渡すことにより、フラグメントの復元を抑制することです。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
    ...
}

もう 1 つの方法は、オンデマンドで PagerAdapter にフラグメントを作成することです。

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0: return Fragment.instantiate(this, Fragment1.class.getName());
        case 1: return Fragment.instantiate(this, Fragment2.class.getName());
        default: throw new RuntimException();
    }
}

この方法でフラグメントのインスタンスを保存します。

@Override
public Object instantiateItem(View container, int position) {
    Fragment fr = (Fragment) super.instantiateItem(container, position);
    fragments[position] = fr;
    return fr;
}

(注:2番目の方法は私がテストしていないため、機能しない可能性があります)

ところで、Android 4.0 の設定で「アクティビティを保持しない」開発者オプションをチェックして、このような問題をテストできます。

于 2012-12-25T05:46:15.767 に答える
0

起こっていることは、フラグメントを含むアクティビティが破棄されたことです。これは、アクティビティが表示されていないときにいつでも発生する可能性があります。ユーザーが行ったのは、アクティビティを積極的に破棄する開発者設定を変更して、このようなコーディングの問題を確認できるようにすることです。問題は依然として発生する可能性があり、デバイスで使用できるリソースが少ないほど (メモリが少ないか、他の多くのものが実行されているため)、Android がこれを行う頻度が高くなります。

onActivityResult()根本的な問題の背景を説明したので、コード内の特定の問題に移りましょう。このメソッドは、ビューのライフサイクルのある時点で、フラグメントとアクティビティに関するコンテキストが再構築される前に呼び出されるため、このメソッドでフラグメントに対して意味のある作業を行うことはできず、常に機能することを確認してください。代わりに、応答をクラス レベルの変数に保存し、それを使用してonResume()、アクティビティが破棄されたかどうかに関係なく呼び出されます。

余談ですが、onActivityResult()メソッドをフラグメントに移動し、常にsuper.onActivityResult()独自のコードの前に呼び出す必要があります。

最後に、Android は独自の気まぐれでフラグメントを破棄して再作成することに注意してください (たとえば、デバイスを回転させると、すべてのフラグメントが破棄されて再作成されます)。したがって、Alex のソリューションが示唆するように、Activity と Fragment のライフサイクルを理解して操作する必要があります。これは、他の診断が難しい問題につながるだけです。

于 2013-04-28T16:44:29.590 に答える