56

I'm stuck here with a problem starting an activity from a Button inside a Fragment. Here is my code:

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 (Here is the button)

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

And this is my 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 itself is working fine. It seems to be an error pausing the FragmentActivity, but i can't figure it out. The only thing I found was this post on google http://code.google.com/p/android/issues/detail?id=19917

I also got through the google example code to make sure I mainly use the same technique...

Edit: to make sure the ClickListener works, I tried a Toast in the onClick method - works perfectly.

Juke
  • 943
  • 1
  • 8
  • 14
  • 1
    Just figured out the following: FragmentActivity crashes when: - pressing home button - turning the orientation of the device - starting an Avtivity - calling finish works fine So for the moment this works for me: Overwrite the onSaveInstanceState method without calling the super method and you're fine. Except for the fact, that the instance state isn't saved :D So this is not really a fix, but may nail down the problem. – Juke Jan 05 '12 at 21:07
  • I just had the same problem - the issue for me was caused when I added a new fragment to my project with an empty layout. It seems that somewhere in the code, if nothing is saved to the bundle during onSaveInstanceState it must cause a null pointer exception. Adding some views to my layouts fixed the issue (after hours spent bashing my head against a wall). I am using android support library v4 revision 10. – Wayne Uroda Sep 05 '12 at 04:26
  • @Juke Is it possible to get same behaviour of TabViewActivity using fragmentation, I want to open a new activity in fragmentation area on selectyion od any tab? – CoDe Oct 06 '12 at 07:07
  • @Juke I am able to draw a new Fragment (not activity) on click of button in fragment view, but if I open same fragment again, it's calling Fragment.onCreateView calling everytime...I do not want to load view everytime..any idea/suggestion. – CoDe Oct 08 '12 at 08:46

4 Answers4

62

Quick fix is

class MyFragment extends Fragment {

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

And wait for update in safe mode :)

Vadim
  • 1,582
  • 2
  • 15
  • 16
48

This is a known problem and I'm shocked to find that no one has filed a bug on the public bug tracker for this.

Your problem stems from this:

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

You should notice that if result is null coming into this code and the first if is not triggered you'll get a NullPointerException if we enter the second if.

It should read:

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

I submitted a patch for this a week or two ago: https://android-review.googlesource.com/31261

Jake Wharton
  • 75,598
  • 23
  • 223
  • 230
  • What will be solution of this issue? Should I use another lib? I have same problem. – Pankaj Kumar Feb 14 '12 at 12:20
  • Patch the bug, recompile the support library yourself until the next version comes out. Its sources are in `SDK/extras/android/support/v4/src/`. – Jake Wharton Feb 14 '12 at 13:06
  • Can you post steps to recompile this? – Pankaj Kumar Feb 14 '12 at 13:48
  • 3
    @PankajKumar it's pretty simple, just create a new Java project on Eclipse using the source of the `SDK/extras/android/support/v4/src/`, add the SDK library for API 14 `SDK/platforms/android-14/android.jar` in the project libraries and export it as a JAR file. Done! :) – Mokkun Mar 01 '12 at 20:18
  • @Petter Hello, I have followed the instructions found here->http://stackoverflow.com/questions/2636201/how-to-create-a-project-from-existing-source-in-eclipse-and-then-find-it (I remembered eclipse had an option for creating project from existing source... maybe I am wrong) Any way I have followed the steps found in the above link and Petter suggestions. I have changed the jar in my project and used the newly generated one but now when a FragmentActivity is started a java.lang.NoClassDefFoundError is thrown, have anyone got that issue? – maxsap Mar 06 '12 at 15:46
  • @maxsap ,@Pankaj Kumar u have got any solution ? I have same issue – Parag Chauhan Apr 02 '12 at 12:28
  • 13
    I've applied the changes Jake outlined above and compiled a new support library to use until Google releases his fix. http://ara.sh/android/android-support-v4.jar – Arash Payan Apr 02 '12 at 17:07
  • @JakeWharton I just ran into this today. The most recent version of the support lib fixes the issue. – Christopher Perry Aug 26 '12 at 19:33
  • @ArashPayan Very Much Thank You guy, I got stucked without this jar now I resolved my issue with that jar, You have done a great job for me. thanks! – RajeshVijayakumar Dec 20 '12 at 06:38
  • Will it help if I use [android-support-v13.jar] instead of [android-support-v4.jar] ? – RRTW Apr 25 '13 at 08:06
32

According to a post here, you should be using FragmentStatePagerAdapter rather than FragmentPagerAdapter. I had the same problem you described, and making that switch worked for me.

Harlo Holmes
  • 5,145
  • 1
  • 23
  • 20
  • 2
    Fixed the problem for me as well – starkej2 Sep 21 '12 at 14:20
  • Same here. Any idea why is this? –  Mar 31 '13 at 19:14
  • 3
    Having this problem, even if using FragmentStatePagerAdapter (using v13 support lib) – gardarh May 16 '13 at 13:52
  • I had similar problem using v13 support lib. I was using FragmentStatePagerAdapter and it was fine until I tried to add third page. Adding another page crashed the app with NPE above in the question. Ironically, the solution was to **switch back to FragmentPagerAdapter**. – pkk Aug 23 '13 at 11:58
4

I just had the same problem - the issue for me was caused when I added a new fragment to my project with an empty layout. It seems that if nothing is saved to the bundle during Fragment.onSaveInstanceState(Bundle outState) it causes a null pointer exception in FragmentManagerImpl.saveFragmentBasicState.

Adding some views to my layouts fixed the issue (after hours spent bashing my head against a wall). Using android support library v4 revision 10.

Also when using a ListView as the root for the fragment layout, if the listview has no elements you will also get the crash. In the fragment class, override onSaveInstanceState like this to put some data in the bundle:

@Override
public void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);
    outState.putString("DO NOT CRASH", "OK");
}
Wayne Uroda
  • 5,025
  • 4
  • 30
  • 35
  • Both your and Vadim's solutions worked for me. I am using support v13 FragmentStatePageAdapter. Yours is more fun though. – Joey Harwood Apr 16 '15 at 21:36