deadfish
deadfish

Reputation: 12304

OnLoadFinished in fragment causes NullPointerException, unnable to fix or reproduce the crash

I have app where by using fragmentManager I manage fragments. One of the fragments list is WikiItemsFragment

My problem is about NullPointerException in OnLoadFinished

x.x.fragments.WikiItemsFragment.onLoadFinished (WikiItemsFragment.java:97)
x.x.fragments.WikiItemsFragment.onLoadFinished (WikiItemsFragment.java:33)

where line 33 is describing this fragment class, and line 97 is describing adapter.swapCursor(cursor);

Well I still cannot reproduce problem but I know it happen due crash raports and it happened to me only few times. I still don't understand what am I doing wrong that my app crashes in OnLoadFinished method/ How could I force to make my fragment crashed? How could I fix it or even reproduce it? I am working on Nexus 4.

public class WikiItemsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

public static String TAG = WikiItemsFragment.class.getSimpleName();
private ListView listView;
private TextView emptyView;
private TextView wikiItemsInfoBar;
private CursorAdapter adapter;
private Uri uri;
private String[] array;


public static WikiItemsFragment getInstance(Uri contentUri, String[] projectionArray) {
    WikiItemsFragment f = new WikiItemsFragment();
    Bundle bundle = new Bundle();
    bundle.putParcelable("uri", contentUri);
    bundle.putStringArray("array", projectionArray);
    f.setArguments(bundle);
    return f;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_wiki_items, null);

    listView = (ListView) view.findViewById(R.id.listView);
    emptyView = (TextView) view.findViewById(R.id.empty_list);
    emptyView.setTypeface(Core.robotoRegular);
    wikiItemsInfoBar = (TextView) view.findViewById(R.id.wiki_items_info_bar);
    wikiItemsInfoBar.setTypeface(Core.robotoRegular);

    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    uri = getArguments().getParcelable("uri");
    array = getArguments().getStringArray("array");

    if (uri == WikiItemsOffensiveTable.CONTENT_URI)
        adapter = new WikiItemsOffensiveAdapter(getActivity());
    else if (uri == WikiItemsDefensiveTable.CONTENT_URI)
        adapter = new WikiItemsDefensiveAdapter(getActivity());
    else if (uri == WikiItemsOtherTable.CONTENT_URI)
        adapter = new WikiItemsOtherAdapter(getActivity());
    else if (uri == WikiItemsUsableTable.CONTENT_URI)
        adapter = new WikiItemsUsableAdapter(getActivity());
    else if (uri == WikiItemsSpecialTable.CONTENT_URI)
        adapter = new WikiItemsSpecialAdapter(getActivity());
    else if (uri == WikiItemsArtifactTable.CONTENT_URI)
        adapter = new WikiItemsArtifactAdapter(getActivity());

    listView.setAdapter(adapter);

}

@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
    return new CursorLoader(getActivity(), uri, array, null, null, null);
}

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {

    adapter.swapCursor(cursor);
}

@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
    adapter.swapCursor(null);
}

@Override
public void onResume() {
    super.onResume();
    getLoaderManager().initLoader(0, null, this);
}

@Override
public void onPause() {
    super.onPause();
    adapter.swapCursor(null);
}
}

Upvotes: 0

Views: 530

Answers (2)

deadfish
deadfish

Reputation: 12304

Found solution but I didn't really fully understand what had happened.. I had to change if statements to UriMatcher. Somehow comparing uri with string uri didn't work always. Sometimes I was comparing element1 with element1 and it was saying, hey it is not the same! Very strange.

Upvotes: 0

Simas
Simas

Reputation: 44118

Since CursorAdapter can use a null value for the method swapCursor, it must be that onLoadFinished was called before the adapter was set.

Actually it looks like you issued a lot of ifs here:

if (uri == WikiItemsOffensiveTable.CONTENT_URI)
    adapter = new WikiItemsOffensiveAdapter(getActivity());
else if (uri == WikiItemsDefensiveTable.CONTENT_URI)
    adapter = new WikiItemsDefensiveAdapter(getActivity());
else if (uri == WikiItemsOtherTable.CONTENT_URI)
    adapter = new WikiItemsOtherAdapter(getActivity());
else if (uri == WikiItemsUsableTable.CONTENT_URI)
    adapter = new WikiItemsUsableAdapter(getActivity());
else if (uri == WikiItemsSpecialTable.CONTENT_URI)
    adapter = new WikiItemsSpecialAdapter(getActivity());
else if (uri == WikiItemsArtifactTable.CONTENT_URI)
    adapter = new WikiItemsArtifactAdapter(getActivity());

But what if else? You must be getting another uri (possibly null, if args not set), so create a default adapter or log an error then. like this:

if (uri == WikiItemsOffensiveTable.CONTENT_URI)
    adapter = new WikiItemsOffensiveAdapter(getActivity());
else if ...
...
else
    Log.e("Oh no", "The uri was not recognized. Adapter was not created");

Upvotes: 1

Related Questions