在适配器和片段之间实现接口回调时获取NPE

时间:2016-05-21 00:59:01

标签: android nullpointerexception recycler-adapter

我是Android开发的新手,我正在使用此代码实现适配器和fragmnet之间的回调。

BookAdapter

public class BookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{


    private OnButtonClickListener onButtonClickListener;

    //List of books
    private List<BookItems> mBookItems;

    private final int VIEW_ITEM = 0;
    private final int VIEW_PROG = 1;

    private int lastPosition = -1;

    public void OnButtonClickListener (OnButtonClickListener onButtonClickListener) {
        this.onButtonClickListener = onButtonClickListener;
    }

    public interface OnButtonClickListener {
        void onButtonClick();
    }

   public BookAdapter(List<BookItems> bookItems, Context context) {
       super();

       //Getting all books
       this.mBookItems = bookItems;
       this.mContext = context;
   }


    @Override
    public int getItemViewType(int position) {
        if (isPositionItem(position))
            return VIEW_ITEM;
        return VIEW_PROG;
    }

    private boolean isPositionItem(int position) {
       return position != getItemCount()-1;
    }



    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder (ViewGroup parent, int viewType) {
        if (viewType == VIEW_ITEM) {
            View v =  LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.book_summ, parent, false);
            return new TextViewHolder(v);
        } else if (viewType == VIEW_PROG){
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recyclerfooter, parent, false);
            return new ProgressViewHolder(v);
        }

        return null;
    }



    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof TextViewHolder) {
            final BookItems bookList = mBookItems.get(position);
            /...

        } else {
            ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
            ((ProgressViewHolder) holder).loadButton.setText(R.string.reload);
        }


    }

    @Override
    public int getItemCount(){
        //Return the number of items in the data set
        return mBookItems.size();
    }

    public class TextViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        ...
        }


    public  class ProgressViewHolder extends RecyclerView.ViewHolder implements  View.OnClickListener{
        Button loadButton;
        ProgressBar progressBar;
        public ProgressViewHolder(View footerView){
            super(footerView);
           ...
        }

        @Override
        public void onClick(View v) {
            if (v.getId() == loadButton.getId()) {
                        onButtonClickListener.onButtonClick();

            }
        }
    }


}

BookFragment

public class BookFragment extends Fragment implements BookAdapter.OnButtonClickListener{


    BookAdapter mAdapter;

    //Creating a list of books
    private List<BookItems> mBookItemsList;

    //Creating Views
    ObservableRecyclerView recyclerView;
    private String title;
    private RecyclerView.Adapter adapter;
    private ProgressDialog mProgressDialog;
    SwipeRefreshLayout mSwipeRefreshLayout;
    LinearLayoutManager mLayoutManager;



    public BookFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAdapter = new BookAdapter(mBookItemsList,getContext());
        mAdapter.OnButtonClickListener(this);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        title = getArguments().getString("title");
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_book, container, false);

        //Initializing Views
        ...

        return view;
    }

    ... 

    @Override
    public void onButtonClick() {
        Log.d(TAG, "I recieved it Sir");
        Toast.makeText(getActivity(), "blag blag", Toast.LENGTH_SHORT).show();
    }
}

每次点击loadButton时,应用程序都会因nullpointer异常而崩溃。 你知道为什么会发生这种情况以及如何纠正这个问题吗?

logcat的

05-21 01:34:17.710 20717-20717/com.myapp.bookman E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.myapp.bookman, PID: 20717
                                                                     java.lang.NullPointerException: Attempt to invoke interface method 'void com.myapp.bookman.BookAdapter$OnButtonClickListener.onButtonClick()' on a null object reference
                                                                         at com.myapp.bookman.BookAdapter$ProgressViewHolder.onClick(BookAdapter.java:251)
                                                                         at android.view.View.performClick(View.java:5076)
                                                                         at android.view.View$PerformClick.run(View.java:20279)
                                                                         at android.os.Handler.handleCallback(Handler.java:739)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:135)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5910)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:372)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)

在堆栈跟踪行251中, BookAdapter

中的行onButtonClickListener.onButtonClick();

实施TychoTheTaco回答后

BookAdapter

public class BookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{




    //List of books
    private List<BookItems> mBookItems;

    private final int VIEW_ITEM = 0;
    private final int VIEW_PROG = 1;

    private int lastPosition = -1;

    public void OnButtonClickListener (OnButtonClickListener onButtonClickListener) {
        this.onButtonClickListener = onButtonClickListener;
    }

    public interface OnButtonClickListener {
        void onButtonClick();
    }

   public BookAdapter(List<BookItems> bookItems, Context context) {
       super();

       //Getting all books
       this.mBookItems = bookItems;
       this.mContext = context;
   }


    @Override
    public int getItemViewType(int position) {
        if (isPositionItem(position))
            return VIEW_ITEM;
        return VIEW_PROG;
    }

    private boolean isPositionItem(int position) {
       return position != getItemCount()-1;
    }



    @Override
    public RecyclerView.ViewHolder  onCreateViewHolder (ViewGroup parent, int viewType) {
        if (viewType == VIEW_ITEM) {
            View v =  LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.book_summ, parent, false);
            return new TextViewHolder(v);
        } else if (viewType == VIEW_PROG){
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.recyclerfooter, parent, false);
            return new ProgressViewHolder(v);
        }

        return null;
    }



    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof TextViewHolder) {
            final BookItems bookList = mBookItems.get(position);
            /...

        } else {
            ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
            ((ProgressViewHolder) holder).loadButton.setText(R.string.reload);
        }


    }

    @Override
    public int getItemCount(){
        //Return the number of items in the data set
        return mBookItems.size();
    }

    public class TextViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        ...
        }


    public  class ProgressViewHolder extends RecyclerView.ViewHolder implements  View.OnClickListener{
        Button loadButton;
        ProgressBar progressBar;
        public ProgressViewHolder(View footerView){
            super(footerView);
           ...
        }

        @Override
        public void onClick(View v) {
            if (v.getId() == loadButton.getId()) {
                        onButtonClickListener.onButtonClick();

            }
        }
    }


}

BookFragment

    public class BookFragment extends Fragment implements BookAdapter.OnButtonClickListener{


        BookAdapter mAdapter;

        //Creating a list of books
        private List<BookItems> mBookItemsList;

        //Creating Views
        ObservableRecyclerView recyclerView;
        private String title;
        private RecyclerView.Adapter adapter;
        private ProgressDialog mProgressDialog;
        SwipeRefreshLayout mSwipeRefreshLayout;
        LinearLayoutManager mLayoutManager;



        public BookFragment() {
            // Required empty public constructor
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mAdapter = new BookAdapter(mBookItemsList,getContext());
            mAdapter.OnButtonClickListener(this);
        }


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            title = getArguments().getString("title");
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_book, container, false);

            //Initializing Views
            ...

            return view;
        }

        ... 
        OnButtonClickListener onButtonClickListener = new OnButtonClickListener() {
        @Override
        public void onButtonClick() {
            Log.d(TAG, "I recieved it Sir");
            Toast.makeText(getActivity(), "blag blag", Toast.LENGTH_SHORT).show();
        }
    }
}

问题是 BookAdapter onButtonClickListenerthis.onButtonClickListener = onButtonClickListener;,Android工作室说“无法解析onButtonClickListener上的符号”

而且,在 BookFragment 中,在行public class BookFragment extends Fragment implements BookAdapter.OnButtonClickListener中我要么声明类抽象,要么在OnButtonClickListener中实现onButtoClick()。

1 个答案:

答案 0 :(得分:0)

您创建了private OnButtonClickListener onButtonClickListener;,但它永远不会被分配,所以当您致电onButtonClickListener.onButtonClick();时,它会给出一个NPE。

BookAdapter 中,替换

private OnButtonClickListener onButtonClickListener;

OnButtonClickListener onButtonClickListener = new OnButtonClickListener(){ @Override public void onButtonClick(){ //Do stuff } };