获取项目计数中回收器视图适配器中的空指针expetion

时间:2021-01-22 14:49:11

标签: java android class android-recyclerview adapter

嗨,我是 android 的初学者,仍在学习,我正在制作一个具有一些功能的图书库应用程序,并且在回收器视图适配器中的获取项目计数中存在错误或空指针异常这是第一次发生这样的事情,谢谢。

适配器:

package com.example.newbookstoreplzwork;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.TransitionManager;

import com.bumptech.glide.Glide;

import java.util.ArrayList;

public class BookRecViewAdapter extends RecyclerView.Adapter<BookRecViewAdapter.ViewHolder> {
    private static final String TAG = "BookRecViewAdapter";
     ArrayList<Book> books = new ArrayList<>();
    private Context mcontexet;
    private String parent;
    public BookRecViewAdapter(Context mcontexet , String parent) {
        this.mcontexet = mcontexet;
        this.parent = parent;
    }
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout   .list_item_book , parent ,  false);
       return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        Log.d(TAG, "onBindViewHolder: Working!!!!!");
        holder.txtName.setText(books.get(position).getName());
        Glide.with(mcontexet).asBitmap().load(books.get(position).getImageUrl()).into(holder.imgBook);
        holder.txtDescreption.setText(books.get(position).getShortDesc());
        holder.txtAuthor.setText(books.get(position).getAuthor());
        if (books.get(position).isExpanded()){
            TransitionManager.beginDelayedTransition(holder.parent);
            holder.expandedRealtiveLayout.setVisibility(View.VISIBLE);
            holder.downArrow.setVisibility(View.GONE);

            if (parent.equals(All_Books_Actvity.parentActvity)){
                holder.delete.setVisibility(View.GONE);
            }
            if (parent.equals(Book.fav)){

                holder.delete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AlertDialog.Builder dialog = new AlertDialog.Builder(mcontexet);
                        dialog.setMessage("Are you sure You want to delete " + books.get(position).getName());
                        dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (Utils.getInstance(mcontexet).removeFromFav(books.get(position))) {
                                    Toast.makeText(mcontexet, " Book removed", Toast.LENGTH_SHORT).show();
                                    notifyDataSetChanged();
                                }
                            }
                        });
                        dialog.setNegativeButton("no", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        });
                        dialog.create().show();
                    }
                });
            }else if (parent.equals(Book.already)){
                holder.delete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AlertDialog.Builder dialog = new AlertDialog.Builder(mcontexet);
                        dialog.setMessage("Are you sure You want to delete " + books.get(position).getName());
                        dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (Utils.getInstance(mcontexet).removeLreadyRead(books.get(position))) {
                                    Toast.makeText(mcontexet, " Book removed", Toast.LENGTH_SHORT).show();
                                    notifyDataSetChanged();
                                }
                            }
                        });
                        dialog.setNegativeButton("no", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        });
                        dialog.create().show();
                    }
                });
            } else if (parent.equals(Book.currently)){
                holder.delete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AlertDialog.Builder dialog = new AlertDialog.Builder(mcontexet);
                        dialog.setMessage("Are you sure You want to delete " + books.get(position).getName());
                        dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (Utils.getInstance(mcontexet).removeFromCurrently(books.get(position))) {
                                    Toast.makeText(mcontexet, " Book removed", Toast.LENGTH_SHORT).show();
                                    notifyDataSetChanged();
                                }
                            }
                        });
                        dialog.setNegativeButton("no", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        });

                        dialog.create().show();
                    }

                });


            }else{
                holder.delete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AlertDialog.Builder dialog = new AlertDialog.Builder(mcontexet);
                        dialog.setMessage("Are you sure You want to delete " + books.get(position).getName());
                        dialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (Utils.getInstance(mcontexet).removeFromWantToRead(books.get(position))){
                                    Toast.makeText(mcontexet, "Book Removed", Toast.LENGTH_SHORT).show();
                                }
                            }
                        });
                        dialog.setNegativeButton("no", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        });
                        dialog.create().show();
                    }
                });
            }



        }else{
            TransitionManager.beginDelayedTransition(holder.parent);
            holder.expandedRealtiveLayout.setVisibility(View.GONE);
            holder.downArrow.setVisibility(View.VISIBLE);
        }
        holder.parent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                    Intent intent = new Intent(mcontexet , Book_Actvity.class);
                    intent.putExtra(Book_Actvity.BOOK_ID ,books.get(position).getId());
                    mcontexet.startActivity(intent);

            }
        });


    }
    @Override
    public int getItemCount() {
        return Utils.getInstance(mcontexet).getAllBooksArrayList().size();
    }
    public void setBooks(ArrayList<Book> books) {
        this.books = books;
        notifyDataSetChanged();
    }
    public class ViewHolder extends RecyclerView.ViewHolder{
        private CardView parent;
        private ImageView imgBook;
        private TextView txtName , txtDescreption , txtAuthor ;
        private RelativeLayout expandedRealtiveLayout;
        private ImageView upArrow , downArrow , delete;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            parent = itemView.findViewById(R.id.parent);
            imgBook = itemView.findViewById(R.id.imgBook);
            txtName = itemView.findViewById(R.id.txtBookName);
            txtDescreption = itemView.findViewById(R.id.txtShortDesc);
            expandedRealtiveLayout = itemView.findViewById(R.id.expandedRealtiveLayout);
            upArrow = itemView.findViewById(R.id.btnArrowUpp);
            downArrow = itemView.findViewById(R.id.btnArrowDown);
            txtAuthor = itemView.findViewById(R.id.txtAuthor);
            delete = itemView.findViewById(R.id.btnDelete);
            downArrow.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Book book = books.get(getAdapterPosition());
                    book.setExpanded(!book.isExpanded());
                    notifyItemChanged(getAdapterPosition());
                }
            });
            upArrow.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Book book = books.get(getAdapterPosition());
                    book.setExpanded(!book.isExpanded());
                    notifyItemChanged(getAdapterPosition());
                }
            });
        }

    }


}

实用类

        package com.example.newbookstoreplzwork;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.view.inputmethod.InlineSuggestionsRequest;
    
    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    
    import java.lang.reflect.Type;
    imp

ort java.util.ArrayList;


public class Utils {
    private SharedPreferences sharedPreferences;
    public static Utils instance;
    private static final String ALL_Books = "ALLBOOKS";
    private static String DB_KEY = "db";
    public static final String booksIntext = "booksInText";
    private static final String ALREADY_READ_BOOKS = "AlreadyReadArraylist";
    private static final String FAVOURITE_BOOKS = "Favourite_Books";
    private static final String CURRENTLY_READING_BOOKS = "Currently_Reading_Books";
    private static final String WANT_TO_READ_BOOKS = "Want_To_Read_Books";
    private static ArrayList<Book> allBooksArrayList;

    Utils(Context context) {
        sharedPreferences = context.getSharedPreferences(DB_KEY, Context.MODE_PRIVATE);
        if (null == getAllBooksArrayList()) {
            initData();
        }
        SharedPreferences.Editor editor = sharedPreferences.edit();
        Gson gson = new Gson();
        if (getCurrentlyReadingArrayList() == null) {
            editor.putString(CURRENTLY_READING_BOOKS, gson.toJson(new ArrayList<Book>()));
            editor.commit();

        }
        if (getAlreadyReadArrayList() == null) {
            editor.putString(ALREADY_READ_BOOKS, gson.toJson(new ArrayList<Book>()));
            editor.commit();

        }
        if (getWishListArrayList() == null) {
            editor.putString(WANT_TO_READ_BOOKS, gson.toJson(new ArrayList<Book>()));
            editor.commit();

        }
        if (getFavoritesArrayList() == null) {
            editor.putString(FAVOURITE_BOOKS, gson.toJson(new ArrayList<Book>()));
            editor.commit();

        }

    }


    private void initData() {
        ArrayList<Book> books = new ArrayList<>();
        books.add(new Book(1, "wimpy kid", "karam Shadi", 134, "https://kbimages1-a.akamaihd.net/a93f1391-68be-478b-acb0-63cd7881aed8/1200/1200/False/the-getaway-diary-of-a-wimpy-kid-book-12.jpg",
                "asdfasd", "jhkjhkhkjhkjghjghgfg"));
        books.add(new Book(2, "majduddin Book", "majduddin", 90, "https://s3images.coroflot.com/user_files/individual_files/702459_am5ekrun22pd6wav_kbesce8q.png ", "long", "dodo"));
        SharedPreferences.Editor editor = sharedPreferences.edit();
        Gson gson = new Gson();
        String booksInText = gson.toJson(books);
        editor.putString(booksInText, booksInText);
        editor.commit();

    }

    public static Utils getInstance(Context context) {
        if (instance != null) {

            return instance;
        } else {
            instance = new Utils(context);
            return instance;
        }
    }


    public ArrayList<Book> getCurrentlyReadingArrayList() {
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Book>>() {
        }.getType();
        ArrayList<Book> books = gson.fromJson(sharedPreferences.getString(CURRENTLY_READING_BOOKS, null), type);
        return books;
    }

    public ArrayList<Book> getAlreadyReadArrayList() {
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Book>>() {
        }.getType();
        ArrayList<Book> books = gson.fromJson(sharedPreferences.getString(ALREADY_READ_BOOKS, null), type);
        return books;
    }

    public ArrayList<Book> getWishListArrayList() {
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Book>>() {
        }.getType();
        ArrayList<Book> books = gson.fromJson(sharedPreferences.getString(WANT_TO_READ_BOOKS, null), type);
        return books;
    }

    public ArrayList<Book> getFavoritesArrayList() {
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Book>>() {
        }.getType();
        ArrayList<Book> books = gson.fromJson(sharedPreferences.getString(FAVOURITE_BOOKS, null), type);
        return books;
    }

    public  ArrayList<Book> getAllBooksArrayList() {
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Book>>() {}.getType();
        ArrayList<Book> books = gson.fromJson(sharedPreferences.getString(ALL_Books, null), type);
        return books;
    }


    public Book getBookById(int id) {
        ArrayList<Book> books = getAllBooksArrayList();
        if (null != books) {
            for (Book b : books) {
                if (b.getId() == id) {
                    return b;
                }
            }
        }
        return null;
    }

    public boolean addToAlreadyReadBooks(Book book) {
        ArrayList<Book> books = getAlreadyReadArrayList();
        if (null != books) {
            if (books.add(book)) {
                SharedPreferences.Editor editor = sharedPreferences.edit();
                Gson gson = new Gson();
                editor.remove(ALREADY_READ_BOOKS);
                editor.putString(ALREADY_READ_BOOKS, gson.toJson(books));
                editor.commit();
                return true;
            }
        }
        return false;
    }

    public boolean addToCurrentlyReadingBooks(Book book) {
        ArrayList<Book> books = getCurrentlyReadingArrayList();
        if (null != books) {
            if (books.add(book)) {
                SharedPreferences.Editor editor = sharedPreferences.edit();
                Gson gson = new Gson();
                editor.remove(CURRENTLY_READING_BOOKS);
                editor.putString(CURRENTLY_READING_BOOKS, gson.toJson(books));
                editor.commit();
                return true;
            }
        }
        return false;
    }

    public boolean addToFavourites(Book book) {
        ArrayList<Book> books = getFavoritesArrayList();
        if (null != books) {
            if (books.add(book)) {
                SharedPreferences.Editor editor = sharedPreferences.edit();
                Gson gson = new Gson();
                editor.remove(FAVOURITE_BOOKS);
                editor.putString(FAVOURITE_BOOKS, gson.toJson(books));
                editor.commit();
                return true;
            }
        }
        return false;
    }

    public boolean addTOWantToWantToRead(Book book) {
        ArrayList<Book> books = getWishListArrayList();
        if (null != books) {
            if (books.add(book)) {
                SharedPreferences.Editor editor = sharedPreferences.edit();
                Gson gson = new Gson();
                editor.remove(WANT_TO_READ_BOOKS);
                editor.putString(WANT_TO_READ_BOOKS, gson.toJson(books));
                editor.commit();
                return true;
            }
        }
        return false;
    }

    public boolean removeFromFav(Book book) {
        ArrayList<Book> books = getFavoritesArrayList();
        if (null != books) {
            for (Book b : books) {
                if (b.getId() == book.getId()) {
                    if (books.remove(b)) {
                        Gson gson = new Gson();
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.remove(FAVOURITE_BOOKS);
                        editor.putString(FAVOURITE_BOOKS, gson.toJson(books));
                        editor.commit();
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean removeFromCurrently(Book book) {
        ArrayList<Book>books = getCurrentlyReadingArrayList();
        if (null!=books){
            for (Book b: books){
                if (b.getId() == book.getId()){
                    if (books.remove(b)){
                        Gson gson = new Gson();
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.remove(CURRENTLY_READING_BOOKS);
                        editor.putString(CURRENTLY_READING_BOOKS , gson.toJson(books));
                        editor.commit();
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean removeLreadyRead(Book book) {
        ArrayList<Book>books = getAlreadyReadArrayList();
        if (null!=books){
            for (Book b: books){
                if (b.getId() == book.getId()){
                    if (books.remove(b)){
                        Gson gson = new Gson();
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.remove(ALREADY_READ_BOOKS);
                        editor.putString(ALREADY_READ_BOOKS , gson.toJson(books));
                        editor.commit();
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public boolean removeFromWantToRead(Book book) {
        ArrayList<Book>books = getWishListArrayList();
        if (null!=books){
            for (Book b: books){
                if (b.getId() == book.getId()){
                    if (books.remove(b)){
                        Gson gson = new Gson();
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.remove(WANT_TO_READ_BOOKS);
                        editor.putString(WANT_TO_READ_BOOKS , gson.toJson(books));
                        editor.commit();
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

错误信息:

    java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
    at com.example.newbookstoreplzwork.BookRecViewAdapter.getItemCount(BookRecViewAdapter.java:179)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4044)
    at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3534)
    at android.view.View.measure(View.java:25086)
    at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:792)
    at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:480)
    at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:134)
    at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:277)
    at androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:119)
    at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1578)
    at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1690)
    at android.view.View.measure(View.java:25086)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6872)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:146)
    at android.view.View.measure(View.java:25086)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6872)
    at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:490)
    at android.view.View.measure(View.java:25086)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6872)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at android.view.View.measure(View.java:25086)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6872)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
    at android.view.View.measure(View.java:25086)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6872)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:742)
    at android.view.View.measure(View.java:25086)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3083)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1857)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2146)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1745)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7768)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:967)
    at android.view.Choreographer.doCallbacks(Choreographer.java:791)
    at android.view.Choreographer.doFrame(Choreographer.java:726)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

我真的很抱歉读起来有点长,但我真的不知道该复制什么才能知道什么就足够了

2 个答案:

答案 0 :(得分:0)

试试下面的方法

update/

答案 1 :(得分:0)

在您的适配器中,您使用此 ArrayList<Book> books = new ArrayList<>(); 将数据设置为项目。

但在这里

@Override
    public int getItemCount() {
        return Utils.getInstance(mcontexet).getAllBooksArrayList().size();
    }

问题很大,

您面临的当前问题是因为 Utils.getInstance(mcontexet).getAllBooksArrayList() 返回 null,在 size() 上调用 null 导致 NPE

假设它不返回空值,那么有时您可能会得到 IndexOutOfBoundUtils.getInstance(mcontexet).getAllBooksArrayList() 会返回大小为 5 的 ArrayList 但您用来设置的 books要查看的数据大小为 4,然后为 IOB

假设您也进行了转义,Utils.getInstance(mcontexet).getAllBooksArrayList() 返回大小为 4 的 ArrayListbooks 的大小为 5,那么一个元素将不会显示。

最佳做法是始终创建一个最终的 Collection 实例,然后清除、添加、删除和通知适配器。

推荐的解决方案

final ArrayList<Book> books = new ArrayList<>();

public BookRecViewAdapter(Context mcontexet , String parent) {
        this.mcontexet = mcontexet;
        this.parent = parent;
        books.addAll(Utils.getInstance(mcontexet).getAllBooksArrayList());
        //if you want data from `Utils.getInstance(mcontexet).getAllBooksArrayList()`,
        //even if it returns null, the book is not null, So no **NPE**
    }


    @Override
    public int getItemCount() {
        return books.size();
    }

    public void setBooks(ArrayList<Book> books) {
        //this.books = books; derefrencing can be dangerours, argument books can be null at times
        this.books.clear();//remove this line if you want to keep previous items too.
        this.books.addAll(books);
        notifyDataSetChanged();
    }