tomhogenkamp
tomhogenkamp

Reputation: 83

Why does getActivity returns null in Fragment in ViewPager?

I have a MainActivity and from there I have ViewPager with two Fragments. I want to change properties of Views of FragmentOne from FragmentTwo. So what I have is a callback method from FragmentTwo to the MainActivity. The callback method is shown here:

@Override
public void newMessage(String message) {

    CalculatorFragment calculatorFragment = (CalculatorFragment) fragmentPagerAdapter.getItem(CALCULATOR_FRAGMENT);

    switch (message){
        case SettingsFragment.CHANGE_COLOR:
           //((TextView)view.findViewById(R.id.textViewSum)).setTextColor(Color.RED);
            break;
        case SettingsFragment.NEW_PICTURE:
            calculatorFragment.setBackground();
            break;
        default:
            break;
    }
}

This works all fine. When the user picks a new Picture in FragmentTwo I call the FragmentOne's (CalculatorFragment) method setBackground to set the new picture. Here is how the setBackground method looks like:

public void setBackground(){
    final Bitmap bitmap = new ImageSaver(getActivity()).load();

    if(bitmap != null){
        imageViewBackground.setImageBitmap(bitmap);

    }
}

Here do I get a nullpointer exception by loading the picture because the getActivity() returns null.

EDIT Here is the code where I create the ViewPager:

public static final int CALCULATOR_FRAGMENT = 0;
public static final int SETTINGS_FRAGMENT = 1;
public static final int FRAGMENTS = 2;

private FragmentPagerAdapter fragmentPagerAdapter;

private ViewPager viewPager;

private List<Fragment> fragments = new ArrayList<Fragment>();

private void initializeFragments(){
    fragments.add(CALCULATOR_FRAGMENT, new CalculatorFragment());
    fragments.add(SETTINGS_FRAGMENT, new SettingsFragment());

    fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()){
        @Override
        public int getCount() {
            return FRAGMENTS;
        }
        @Override
        public Fragment getItem(final int position) {
            return fragments.get(position);
        }
    };

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

    viewPager.setAdapter(fragmentPagerAdapter);
}

EDIT The Logcat:

08-11 11:38:38.189 21996-21996/com.tomhogenkamp.personalcalc E/AndroidRuntime: FATAL EXCEPTION: main
                                                                           Process: com.tomhogenkamp.personalcalc, PID: 21996
                                                                           java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=65537, result=-1, data=Intent { dat=content: flg=0x1 }} to activity {com.tomhogenkamp.personalcalc/com.tomhogenkamp.personalcalc.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.support.v4.app.FragmentActivity.getApplicationContext()' on a null object reference
                                                                               at android.app.ActivityThread.deliverResults(ActivityThread.java:4013)
                                                                               at android.app.ActivityThread.handleSendResult(ActivityThread.java:4063)
                                                                               at android.app.ActivityThread.access$1400(ActivityThread.java:150)
                                                                               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                               at android.os.Looper.loop(Looper.java:168)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:5885)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
                                                                            Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.support.v4.app.FragmentActivity.getApplicationContext()' on a null object reference
                                                                               at com.tomhogenkamp.personalcalc.CalculatorFragment.setBackground(CalculatorFragment.java:558)
                                                                               at com.tomhogenkamp.personalcalc.MainActivity.newMessage(MainActivity.java:69)
                                                                               at com.tomhogenkamp.personalcalc.SettingsFragment.onActivityResult(SettingsFragment.java:118)
                                                                               at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:165)
                                                                               at android.app.Activity.dispatchActivityResult(Activity.java:6467)
                                                                               at android.app.ActivityThread.deliverResults(ActivityThread.java:4009)
                                                                               at android.app.ActivityThread.handleSendResult(ActivityThread.java:4063) 
                                                                               at android.app.ActivityThread.access$1400(ActivityThread.java:150) 
                                                                               at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448) 
                                                                               at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                               at android.os.Looper.loop(Looper.java:168) 
                                                                               at android.app.ActivityThread.main(ActivityThread.java:5885) 
                                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797) 
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687) 

The nullpointer exception only occurs when the app is on background sometimes and then reopening it. So it seems like it has something to do with the Android system that kills processes?

How can I solve this?

Upvotes: 1

Views: 5168

Answers (2)

Marcus Casagrande
Marcus Casagrande

Reputation: 183

Ok, I know this thread is one year old and you probably have a better solution by now. But I'm having exact the same problem as you right now and I just adopted a simple (but maybe not the most elegant) solution here that seems to work pretty well. First I've put a MainActivity field on my FragmentOne like this

private MainActivity dad;

Then I've inserted a constructor like this:

public FragmentOne(MainActivity ctx){
    this();
    this.dad = ctx;
}

Also, I've inserted an empty construcor as well for api safety:

public FragmentOne(){
    super();
}

Then, at the Main activity where I would normally insert the FragmentOne, I used the constructor with the MainActivity constructor.

new FragmentOne(this)

Now you can use your activity instance instead of getActivity() method.

I put it to test and it worked perfectly.


Edit: Even though that solved my problem with the getActivity() method, I was still getting some Null Pointers on a ListView set on my onCreate() method (sometimes it was called normally, also sometimes it gave me the NPE problem. So, after thinking a lot about I decided to change my

@Override
public Fragment getItem(int pos) {
    if (pos == 0){
        return new FragmentOne();
    } else if (pos == 1) {
        return new FragmentTwo();
    }
}

to a List<Fragment> as YOU ALREADY DID and calling

@Override
public Fragment getItem(int pos) {
    return my_frags_list.get(pos);
}

as you did. It seems strange to me to call a new Fragment instance on each getItem call. And after doing this List way, my fragments fields stopped giving me NPEs. So far so good. So now my only concearn is why do android examples on ViewPagers recommend using new FragmentInstance() on each getItem(int pos) call intead of the List<Fragment> solution? Who knows.

Upvotes: 1

kalabalik
kalabalik

Reputation: 3832

Probably the problem is that FragmentOne is not attached to your activity while you are seeing FragmentTwo and therefore has no (or a null) reference to it. Try the following code; put it inside FragmentOne:

private Activity activity;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof Activity) {
        activity = (Activity) context;
    }
}

public void setBackground(){
    final Bitmap bitmap = new ImageSaver(activity).load();

    if(bitmap != null){
        imageViewBackground.setImageBitmap(bitmap);
    }
}

If this doesn't work, please show us the adapter of your ViewPager and, if it not included in the ViewPager, the code where you create your fragments.

Upvotes: 0

Related Questions