实现RecyclerView时出现NullPointerException

时间:2015-07-23 10:53:27

标签: android android-recyclerview recycler-adapter

我正在尝试实施RecyclerView以显示片段中的项目列表。

片段代码:

ng-repeat

适配器:

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.List;

public class SearchFragment extends BaseFragment implements LoaderManager.LoaderCallbacks<StringBuilder> {

    private RecyclerView mRecyclerView;
    private SearchAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    private String searchQuery;

    private User user;

    private OnFragmentInteractionListener mListener;

    public SearchFragment() {
    }

    public static SearchFragment newInstance() {
        SearchFragment fragment = new SearchFragment();
        return fragment;
    }

    public void setSearchQuery(String searchQuery) {
        this.searchQuery = searchQuery;
    }

    public void search() {
        try {
            Bundle bundle = new Bundle();
            bundle.putString(API.DISH_SEARCH_KEY, searchQuery);
            getLoaderManager().restartLoader(LoaderConstants.DISH_SEARCH_LOADER_ID, bundle, SearchFragment.this).forceLoad();
        } catch (IllegalStateException e) {
            // thrown when Fragment not attached to Activity
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            user = new Gson().fromJson(getArguments().getString(API.USER_KEY), User.class);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_search, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.my_recycler_view);

        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager);

        search();

        return view;
    }

    @Override
    public Loader<StringBuilder> onCreateLoader(int id, Bundle bundle) {

        String searchQuery = bundle.getString(API.DISH_SEARCH_KEY);
        String url = String.format(API.DISH_SEARCH_URL, searchQuery);

        bundle.putString(API.URL_KEY, url);
        bundle.putString(API.TYPE_KEY, API.TYPE_GET);

        return new CravyAsyncLoader(getActivity(), bundle);
    }

    @Override
    public void onLoadFinished(Loader<StringBuilder> loader, StringBuilder data) {

        if (Util.isEmptyJsonResponse(data)) {
            Toast.makeText(getActivity(), "No dishes found!", Toast.LENGTH_LONG).show();
            return;
        }

        List<Dish> dishes;
        try {
            // Convert JSONArray response to List<Dish>
            Type listType = new TypeToken<List<Dish>>() {
            }.getType();
            dishes = (List<Dish>) new Gson().fromJson(data.toString(), listType);
        } catch (Exception ex) {
            Toast.makeText(getActivity(), "Something went wrong. Try again.", Toast.LENGTH_LONG).show();
            return;
        }

        if (dishes != null) {
            mAdapter = new SearchAdapter(dishes, SearchFragment.this);
            mRecyclerView.setAdapter(mAdapter);
        }
    }

    @Override
    public void onLoaderReset(Loader<StringBuilder> loader) {
    }
}

我在import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import com.google.gson.Gson; import java.util.List; public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> { private List<Dish> mDishes; private Fragment fragment; public SearchAdapter(List<Dish> dishes, Fragment fragment) { mDishes = dishes; this.fragment = fragment; } // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { // each data item is just a string in this case public LinearLayout mView; private Fragment fragment; public ViewHolder(LinearLayout itemView, Fragment fragment) { super(itemView); this.fragment = fragment; itemView.setClickable(true); itemView.setOnClickListener(this); } @Override public void onClick(View v) { TextView textView = (TextView) v.findViewById(R.id.dish_id); String id = textView.getText().toString(); Dish dish = getDishById(id); Bundle bundle = new Bundle(); bundle.putString(API.DISH_KEY, new Gson().toJson(dish)); // Create new fragment and transaction DishDetailsFragment dishDetailsFragment = DishDetailsFragment.newInstance(bundle); FragmentTransaction transaction = fragment.getFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack transaction.replace(R.id.content, dishDetailsFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit(); } } // Create new views (invoked by the layout manager) @Override public SearchAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LinearLayout view = (LinearLayout) LayoutInflater.from(parent.getContext()) .inflate(R.layout.search_list_item, parent, false); return new ViewHolder(view, fragment); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element ((TextView) holder.mView.findViewById(R.id.dish_id)).setText(mDishes.get(position).getId()); ((TextView) holder.mView.findViewById(R.id.dish_name)).setText(mDishes.get(position).getName()); ((TextView) holder.mView.findViewById(R.id.restaurant_name)).setText(mDishes.get(position).getRestaurantId()); try { ((TextView) holder.mView.findViewById(R.id.price)).setText(String.valueOf(mDishes.get(position).getPrice().getValue())); } catch (Exception ex) { ((TextView) holder.mView.findViewById(R.id.price)).setText("No Price Available"); } } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDishes.size(); } public Dish getDishById(String id) { for (Dish dish : mDishes) { if (dish.getId().equals(id)) return dish; } return null; } }

收到错误
Adapter

错误:

    ((TextView) holder.mView.findViewById(R.id.dish_id)).setText(mDishes.get(position).getId());

我尝试调试应用。它将java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.widget.LinearLayout.findViewById(int)' on a null object reference at com.fonduetech.cravy.adapter.SearchAdapter.onBindViewHolder(SearchAdapter.java:87) at com.fonduetech.cravy.adapter.SearchAdapter.onBindViewHolder(SearchAdapter.java:21) at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:4138) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3448) at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3340) at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1810) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1306) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1269) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:523) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1988) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1000) at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:710) at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42) at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:982) at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:723) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:907) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2086) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1843) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) at android.view.ViewR 显示为mView。为什么呢?

3 个答案:

答案 0 :(得分:1)

   public ViewHolder(LinearLayout itemView, Fragment fragment) {
        super(itemView);
        this.fragment = fragment;
        this.mView = itemView; //this line is missing
        itemView.setClickable(true);
        itemView.setOnClickListener(this);
    }

答案 1 :(得分:0)

您使用的是Android Studio吗?

如果是,只需在build.grade中包含它:

compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'

然后只需同步等级或只需按顶部的平台按钮即可。我想这会给你一些结果

答案 2 :(得分:0)

如果您的RecyclerView适配器没有数据意味着您没有调用setAdapter,那么它将返回Error。

因此,默认情况下,如果您有数据然后首先设置数据,然后设置RecyclerView的Visiable Property,则必须设置RecyclerView的不可见属性。