简体   繁体   English

为什么 getActivity 在 ViewPager 的 Fragment 中返回 null?

[英]Why does getActivity returns null in Fragment in ViewPager?

I have a MainActivity and from there I have ViewPager with two Fragments.我有一个 MainActivity,从那里我有带有两个 Fragment 的 ViewPager。 I want to change properties of Views of FragmentOne from FragmentTwo.我想从 FragmentTwo 更改 FragmentOne 视图的属性。 So what I have is a callback method from FragmentTwo to the MainActivity.所以我有一个从 FragmentTwo 到 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.当用户在 FragmentTwo 中选择一张新图片时,我调用 FragmentOne 的 (CalculatorFragment) 方法 setBackground 来设置新图片。 Here is how the setBackground method looks like: setBackground 方法如下所示:

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.在这里我通过加载图片得到一个空指针异常,因为 getActivity() 返回空值。

EDIT Here is the code where I create the ViewPager:编辑这是我创建 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:编辑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?我该如何解决这个问题?

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.可能的问题是,当您看到FragmentTwo时, FragmentOne没有附加到您的活动,因此没有(或null )对它的引用。 Try the following code;试试下面的代码; put it inside FragmentOne :把它放在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.如果这不起作用,请向我们展示您的ViewPager的适配器,如果它未包含在ViewPager ,请向我们展示您创建片段的代码。

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首先,我像这样在 FragmentOne 上放置了一个 MainActivity 字段

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:另外,为了 api 安全,我还插入了一个空的构造函数:

public FragmentOne(){
    super();
}

Then, at the Main activity where I would normally insert the FragmentOne, I used the constructor with the MainActivity constructor.然后,在我通常会插入 FragmentOne 的 Main 活动中,我将构造函数与 MainActivity 构造函数一起使用。

new FragmentOne(this)

Now you can use your activity instance instead of getActivity() method.现在您可以使用您的活动实例而不是 getActivity() 方法。

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编辑:尽管用 getActivity() 方法解决了我的问题,但我仍然在我的 onCreate() 方法上设置的 ListView 上得到一些空指针(有时它被正常调用,有时它也给了我 NPE 问题。所以,在想了很多之后我决定改变我的

@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 callingList<Fragment>就像你已经做的那样并调用

@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.在每次getItem调用时调用一个新的 Fragment 实例对我来说似乎很奇怪。 And after doing this List way, my fragments fields stopped giving me NPEs.在执行此 List 方式后,我的片段字段不再给我 NPE。 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?所以现在我唯一关心的是为什么 ViewPagers 上的 android 示例建议在List<Fragment>解决方案的每个getItem(int pos)调用上使用new FragmentInstance() Who knows.谁知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM