【问题标题】:Starting Activity from Fragment causes NullPointerException从 Fragment 启动 Activity 导致 NullPointerException
【发布时间】:2012-02-03 14:32:14
【问题描述】:

我遇到了从片段内的按钮启动活动的问题。 这是我的代码:

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 似乎是一个错误,但我无法弄清楚。我唯一发现的是谷歌上的这篇帖子http://code.google.com/p/android/issues/detail?id=19917

我还查看了 google 示例代码,以确保我主要使用相同的技术...

编辑:为确保 ClickListener 正常工作,我在 onClick 方法中尝试了一个 Toast - 完美运行。

【问题讨论】:

  • 刚刚发现以下问题: FragmentActivity 在以下情况下崩溃: - 按下主页按钮 - 转动设备的方向 - 启动 Avtivity - 调用完成工作正常所以目前这对我有用:覆盖 onSaveInstanceState方法而不调用超级方法,你很好。除了没有保存实例状态这一事实之外:D 所以这并不是真正的修复,但可能会解决问题。
  • 我也遇到了同样的问题——对我来说,这个问题是我在项目中添加了一个空布局的新片段时引起的。似乎在代码中的某处,如果在 onSaveInstanceState 期间没有将任何内容保存到包中,则它必须导致空指针异常。在我的布局中添加一些视图解决了这个问题(花了几个小时把我的头撞到墙上)。我正在使用 android 支持库 v4 修订版 10。
  • @Juke 是否可以使用碎片获得与 TabViewActivity 相同的行为,我想在选择或任何选项卡上的碎片区域中打开一个新活动?
  • @Juke 我可以在片段视图中单击按钮时绘制一个新的片段(不是活动),但是如果我再次打开相同的片段,它会调用 Fragment.onCreateView 每次调用......我做不想每次都加载视图..任何想法/建议。

标签: android android-activity android-fragments android-viewpager


【解决方案1】:

我也遇到了同样的问题——我的问题是我在项目中添加了一个空布局的新片段时引起的。似乎如果在Fragment.onSaveInstanceState(Bundle outState) 期间没有将任何内容保存到包中,则会导致FragmentManagerImpl.saveFragmentBasicState 中出现空指针异常。

在我的布局中添加一些视图解决了这个问题(花了几个小时把我的头撞到墙上)。使用 android 支持库 v4 修订版 10。

此外,当使用ListView 作为片段布局的根时,如果列表视图没有元素,您也会遇到崩溃。在片段类中,像这样覆盖onSaveInstanceState 以将一些数据放入包中:

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

【讨论】:

  • 您和 Vadim 的解决方案都对我有用。我正在使用支持 v13 FragmentStatePageAdapter。不过你的更有趣。
【解决方案2】:

根据here 的帖子,您应该使用 FragmentStatePagerAdapter 而不是 FragmentPagerAdapter。我遇到了与您描述的相同的问题,并且使该转换对我有用。

【讨论】:

  • 也为我解决了这个问题
  • 这里也一样。知道这是为什么吗?
  • 有这个问题,即使使用 FragmentStatePagerAdapter(使用 v13 支持库)
  • 我在使用 v13 支持库时遇到了类似的问题。我正在使用 FragmentStatePagerAdapter 并且在我尝试添加第三页之前它很好。在问题中添加另一个页面会使应用程序与上述 NPE 一起崩溃。具有讽刺意味的是,解决方案是切换回 FragmentPagerAdapter
【解决方案3】:

快速修复是

class MyFragment extends Fragment {

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

然后在安全模式下等待更新:)

【讨论】:

  • 顺便说一句,2012 年 3 月的 SupportPackage 更新已修复问题
  • 截至 2012 年 4 月 23 日我仍然遇到这个问题 .. 但这个答案很好地解决了它
  • 奇怪,我自己不使用自己的修复更多:)
  • 哎呀。此修复在少数情况下仍然有效!我返回并继续使用它。
  • @BryanDenny OMG,这也解决了烦人的 ABS 的 FragmentTabPager 示例!只需要把它放在所有声明的 SherlockFragment 中:)
【解决方案4】:

这是一个已知问题,我很震惊地发现没有人为此在公共错误跟踪器上提交错误。

您的问题源于此:

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

您应该注意到,如果resultnull 进入此代码并且第一个if 没有被触发,如果我们输入第二个if,您将得到一个NullPointerException

应该是:

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

我在一两周前为此提交了一个补丁:https://android-review.googlesource.com/31261

【讨论】:

  • 如何解决这个问题?我应该使用另一个库吗?我也有同样的问题。
  • 打补丁,自己重新编译支持库,直到下一个版本出来。其来源在SDK/extras/android/support/v4/src/
  • 你能发布重新编译的步骤吗?
  • @PankajKumar 非常简单,只需使用SDK/extras/android/support/v4/src/ 的源代码在Eclipse 上创建一个新的Java 项目,在项目库中添加API 14 的SDK 库SDK/platforms/android-14/android.jar 并将其导出为JAR 文件。完毕! :)
  • 我已经应用了 Jake 上面概述的更改并编译了一个新的支持库以供使用,直到 Google 发布他的修复程序。 ara.sh/android/android-support-v4.jar
猜你喜欢
  • 1970-01-01
  • 2021-02-18
  • 2021-12-14
  • 1970-01-01
  • 2016-12-19
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多