碎片在返回时会触发NPE

时间:2014-01-29 13:32:53

标签: android android-fragments nullpointerexception

我正在使用此Fragment从服务器加载ListView中的一些数据,但似乎无论何时重新创建(配置已更改),它都会触发NPE,因为当再次调用setListShown时,mProgressContainer为null。我尝试在onCreate中使用setRetainInstance(true),希望每次配置更改都不会再次下载数据,但似乎有些不对劲。 无论如何,即使没有setRetainInstance(true) - 我确实想要使用它,我确信它不应该有这种行为。要清除这些内容,这个片段在第一次加载时就能正常工作,但是如果用于例如。我从纵向更改为横向,它在此行崩溃:

onResponse -> setListShown(true);

修改

public class CategoriesFragment extends ListFragment implements
    Listener<CategoryParsedHolder>, ErrorListener {

private OnCategorySelectedListener mCallback;

private int mTotalArticles = 0;

private CategoriesAdapter listAdapter;

// The container Activity must implement this interface so the fragment can
// deliver messages
public interface OnCategorySelectedListener {

    /** Called by CategoriesFragment when a list item is selected */
    public void onCategorySelected(long id);
}

private static final String SOME_KEY = "id_key";

private long mId;

public CategoriesFragment() {
}

public static CategoriesFragment newInstance(long id) {

    CategoriesFragment f = new CategoriesFragment();

    // add id
    Bundle bundle = new Bundle();
    bundle.putLong(SOME_KEY, id);
    f.setArguments(bundle);

    return f;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getArguments() == null) {
        throw new IllegalArgumentException(
                "No id received in CategoriesFragment");
    }

    mId = getArguments().getLong(SOME_KEY);

}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    if (mCallback != null) {
        mCallback.onCategorySelected(id);
    }
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if (listAdapter == null) {
        listAdapter = new CategoriesAdapter(getActivity());
    }
    setListAdapter(listAdapter);
    setListShown(false);

    new Handler().post(loadCategoriesForTab);

}

final Runnable loadCategoriesForTab = new Runnable() {

    @Override
    public void run() {

        if (NetworkUtil.hasInternetAccess(W2MApp.getW2MAppContext())) {
            W2MApp.getW2MAppContext()
                    .getApi()
                    .getCategories(mId, CategoriesFragment.this,
                            CategoriesFragment.this);
        } else {
            onErrorResponse(new VolleyError(W2MApp.getW2MAppContext()
                    .getResources()
                    .getString(R.string.error_no_internet_connection)));
        }
    }
};

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    try {
        mCallback = (OnCategorySelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnCategorySelectedListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mCallback = null;
}

@Override
public void onResponse(CategoryParsedHolder response) {

    if (response.getCategoriesList() != null)
    {

        listAdapter.updateData(response.getCategoriesList());
        setListShown(true);

    } else {
        // if data is invalid or no data found, call onErrorResponse
        onErrorResponse(new VolleyError(getResources().getString(
                R.string.error_data_not_found)));
    }

}

@Override
public void onErrorResponse(VolleyError error) {

    setListShownNoAnimation(true);

    // TODO set error page here (Oups...)

}

@Override
public void onDestroy() {
    setListAdapter(null);
    MyVolley.cancelPendingRequestsByTag(this);
    super.onDestroy();
}

}

错误日志的一部分在这里:

01-30 10:39:32.318: E/AndroidRuntime(31705): FATAL EXCEPTION: main
01-30 10:39:32.318: E/AndroidRuntime(31705): java.lang.IllegalStateException: Content view not yet created
01-30 10:39:32.318: E/AndroidRuntime(31705):    at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
01-30 10:39:32.318: E/AndroidRuntime(31705):    at android.support.v4.app.ListFragment.setListShown(ListFragment.java:280)
01-30 10:39:32.318: E/AndroidRuntime(31705):    at android.support.v4.app.ListFragment.setListShown(ListFragment.java:258)
01-30 10:39:32.318: E/AndroidRuntime(31705):    at com.example.CategoriesFragment.onResponse(CategoriesFragment.java:147)
01-30 10:39:32.318: E/AndroidRuntime(31705):    at com.example.ui.CategoriesFragment.onResponse(CategoriesFragment.java:1)

基本上它告诉我,当我更改配置并重新创建Fragment时,它会在尝试显示时找不到ListView。关于如何解决这个问题的任何想法?

1 个答案:

答案 0 :(得分:0)

看到你的日志后,我重写了这个答案。

您的NPE发生在loadAnimation内部,这意味着它是传入的活动,为null。这很可能是因为您在片段附加到Activity之后或者在分离之后获得了回调。我会尝试在onAttach / onDetach中注册/取消注册回调,看看是否有帮助。