web-dev-qa-db-ja.com

フラグメントからアクティビティを開始すると、NullPointerExceptionが発生します

ここで、フラグメント内のボタンからアクティビティを開始する際に問題が発生します。ここに私のコードがあります:

ViewPagerAdapter.Java

import Java.util.List;

import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentPagerAdapter;

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;

    public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public int getCount() {
        return this.fragments.size();
    }

    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

}

ViewPagerActivity.Java

import Java.util.List;
import Java.util.Vector;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentActivity;
import Android.support.v4.view.ViewPager;
import Android.util.Log;
import com.package.here.Class1Overview;
import com.package.here.Class1Overview;
import com.package.here.Class1Overview;

public class ViewPagerActivity extends FragmentActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.viewpager);

        ViewPager pager = (ViewPager)super.findViewById(R.id.my_viewpager);
        pager.setAdapter(initialisePaging());
    }

    private ViewPagerAdapter initialisePaging() {

        List<Fragment> fragments = new Vector<Fragment>();
        fragments.add(Fragment.instantiate(this, Class1Overview.class.getName()));
        fragments.add(Fragment.instantiate(this, Class2Overview.class.getName()));
        fragments.add(Fragment.instantiate(this, Class3Overview.class.getName()));
        return new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);          
    }

}

Class1Overview.Java(ここにボタンがあります)

import Android.content.Intent;
import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.view.ViewGroup;
import Android.widget.Button;
import Android.widget.LinearLayout;
import com.package.here.R;

public class FuelOverview extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (container == null) {
            return null;
        }
        View v = (LinearLayout)inflater.inflate(R.layout.class_one_layout, container, false);
        View AddBtn = v.findViewById(R.id.btn_add);
        ((Button) AddBtn).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClass(getActivity(), ActivityToStart.class);
                startActivity(intent);
            }
        });

        return v;
    }
}

そしてこれは私のLogCatです:

01-05 19:39:00.913: E/AndroidRuntime(10557): Uncaught handler: thread main exiting due to uncaught exception
01-05 19:39:01.034: E/AndroidRuntime(10557): Java.lang.RuntimeException: Unable to pause activity {com.package.here/com.package.here.ViewPagerActivity}: Java.lang.NullPointerException
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread.performPauseActivity(ActivityThread.Java:3162)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread.performPauseActivity(ActivityThread.Java:3119)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread.handlePauseActivity(ActivityThread.Java:3102)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread.access$2400(ActivityThread.Java:119)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1870)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.os.Looper.loop(Looper.Java:123)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread.main(ActivityThread.Java:4363)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Java.lang.reflect.Method.invokeNative(Native Method)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Java.lang.reflect.Method.invoke(Method.Java:521)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:860)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:618)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at dalvik.system.NativeStart.main(Native Method)
01-05 19:39:01.034: E/AndroidRuntime(10557): Caused by: Java.lang.NullPointerException
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.Java:1576)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.Java:1617)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.Java:481)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.Activity.performSaveInstanceState(Activity.Java:1022)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.Java:1180)
01-05 19:39:01.034: E/AndroidRuntime(10557):    at Android.app.ActivityThread.performPauseActivity(ActivityThread.Java:3144)
01-05 19:39:01.034: E/AndroidRuntime(10557):    ... 12 more
01-05 19:39:01.423: I/dalvikvm(10557): threadid=7: reacting to signal 3

ViewPager自体は正常に動作しています。 FragmentActivityを一時停止するのはエラーのようですが、わかりません。私が見つけた唯一のことは、Googleのこの投稿でした http://code.google.com/p/Android/issues/detail?id=19917

また、Googleのサンプルコードを使用して、主に同じテクニックを使用するようにしました...

編集:ClickListenerが機能することを確認するために、onClickメソッドでToastを試しました-完全に機能します。

56
Juke

これは既知の問題であり、誰もこのバグを公開バグ追跡システムに報告していないことを知ってショックを受けています。

問題の原因は次のとおりです。

if (f.mSavedViewState != null) {
    if (result == null) {
        result = new Bundle();
    }
    result.putSparseParcelableArray(
            FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
    // Only add this if it's not the default value
    result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}

resultがこのコードに入ってくるnullであり、最初のifがトリガーされない場合、2番目を入力するとNullPointerExceptionが得られることに注意してください。 if

次のようになります。

if (f.mSavedViewState != null) {
    if (result == null) {
        result = new Bundle();
    }
    result.putSparseParcelableArray(
            FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
    if (result == null) {
        result = new Bundle();
    }
    // Only add this if it's not the default value
    result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}

1〜2週間前にこのパッチを提出しました: https://Android-review.googlesource.com/31261

48
Jake Wharton

クイックフィックスは

class MyFragment extends Fragment {

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

そして、セーフモードでの更新を待ちます:)

62
Vadim

投稿によると here 、FragmentPagerAdapterではなくFragmentStatePagerAdapterを使用する必要があります。私があなたが説明したのと同じ問題があり、そのスイッチを作ることは私のために働いた。

32
Harlo Holmes

私はちょうど同じ問題を抱えていました-私にとっての問題は、空のレイアウトでプロジェクトに新しいフラグメントを追加したときに発生しました。 Fragment.onSaveInstanceState(Bundle outState)中にバンドルに何も保存されない場合、FragmentManagerImpl.saveFragmentBasicStateでNULLポインター例外が発生するようです。

レイアウトにいくつかのビューを追加すると、問題が解決しました(数時間かけて頭を壁にぶつけた後)。 Android support library v4 revision 10を使用します。

フラグメントレイアウトのルートとしてListViewを使用する場合、リストビューに要素がない場合もクラッシュします。フラグメントクラスで、次のようにonSaveInstanceStateをオーバーライドして、いくつかのデータをバンドルに入れます。

@Override
public void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);
    outState.putString("DO NOT CRASH", "OK");
}
4
Wayne Uroda