2

I have a cardView adapter which allows me to display data from my database. I have just implemented a swipe to delete but sometimes I have this error:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.unFocus(android.view.View)' on a null object reference

that points to this line of code mRecyclerView.removeViewAt (viewHolder.getAdapterPosition ()); in my Activity

I do not understand why I have this error especially that sometimes it works very well but sometimes not ...

My activity

public class Resume_game_new extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    List<Game> mDataset;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_resume_game_new);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view_resume_game);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mDataset = Data.bdd.getGames();
        mAdapter = new CardsViewAdapter(mDataset);
        mRecyclerView.setAdapter(mAdapter);

        //Swipe to Delete
        ItemTouchHelper swipeToDismissTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
                ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
            {

                // Do Stuff
                TextView textView_id_game = (TextView) viewHolder.itemView.findViewById(R.id.textView16);
                Data.bdd.remove_game(Integer.parseInt(textView_id_game.getText().toString()));
                mDataset.remove(viewHolder.getAdapterPosition());


                mRecyclerView.removeViewAt(viewHolder.getAdapterPosition());
                mAdapter.notifyItemRemoved(viewHolder.getLayoutPosition());
                mAdapter.notifyItemRangeChanged(viewHolder.getAdapterPosition(), mDataset.size());
                mAdapter.notifyDataSetChanged();

            }

        });
        swipeToDismissTouchHelper.attachToRecyclerView(mRecyclerView);
    }

}

My adapter (only revelant code)

public class CardsViewAdapter extends RecyclerView.Adapter<CardsViewAdapter.ViewHolder> {
    private List<Game> mDataset;
    private int rotationAngle = 0;

    // 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
    static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        private TextView textView_idGame;
        private ImageView imageView_arrow;
        private LinearLayout linearlayoutToExpands;
        private ConstraintLayout coordinatorLayoutToExpands;
        boolean isPopupVisible;
        private CardView cardView;


        ViewHolder(View v) {
            super(v);
            textView_idGame = (TextView) v.findViewById(R.id.textView16);
            imageView_arrow = (ImageView) v.findViewById(R.id.item_description_game_more);
            linearlayoutToExpands = (LinearLayout) v.findViewById(R.id.popup_layout);
            isPopupVisible = false;
            cardView = (CardView) v.findViewById(R.id.cardView);


            coordinatorLayoutToExpands = (ConstraintLayout) v.findViewById(R.id.viewToExpands);
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    CardsViewAdapter(List<Game> myDataset) {
        mDataset = myDataset;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public CardsViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.cards_resume_game, parent, false);
        // set the view's size, margins, paddings and layout parameters
        //...

        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        final Game game = mDataset.get(position);

...

        // Set the expanded or collapsed mode here
        if(game.expanded) {
            expandView(holder.coordinatorLayoutToExpands);
            holder.imageView_arrow.setRotation(180);
        }
        else {
            collapseView(holder.coordinatorLayoutToExpands);
            holder.imageView_arrow.setRotation(0);
        }


        // Now set the onClickListener like this
        holder.imageView_arrow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // Animate the imageView here
                animateImageView(holder.imageView_arrow);

                // Toggle the expanded attribute value
                if(game.expanded) game.expanded = false;
                else game.expanded = true;

                 //Now call notifyDataSetChanged to make the change to effect
                refreshList(position);
            }
        });
    }

    // Extra functions inside your adapter class to improve readability
    private void collapseView(View v) {
        CardsAnimationHelper.collapse(v);
    }

    private void expandView(View v) {
        CardsAnimationHelper.expand(v);
    }

    private void refreshList(final int position) {
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyItemChanged(position);
            }
        }, animationDuration);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }


}
filol
  • 1,523
  • 1
  • 12
  • 36

2 Answers2

5

Remove these lines of code from your onSwiped() method

mRecyclerView.removeViewAt(viewHolder.getAdapterPosition());
mAdapter.notifyItemRemoved(viewHolder.getLayoutPosition());
mAdapter.notifyItemRangeChanged(viewHolder.getAdapterPosition(), mDataset.size());

and only use this :

mAdapter.notifyDataSetChanged();

Also note you are using "viewHolder.getLayoutPosition()" instead of "viewHolder.getAdapterPosition()" for notifyItemRemoved.

Also provide your version of cardView support library.

ChaitanyaAtkuri
  • 1,615
  • 9
  • 15
  • Sure of yourself ? I followed what this person said http://stackoverflow.com/a/31368367/7355733 Thanks i fix `viewHolder.getLayoutPosition()` – filol Jan 09 '17 at 13:29
  • Yup @filol give it a try. That manual removal of items from recyclerview is required when you have a tight coupling of data. As you have already removed data from the data set, it should work with notifydatasetchanged(). – ChaitanyaAtkuri Jan 09 '17 at 13:31
  • Of course, you're right and this by pass my problem – filol Jan 09 '17 at 13:37
0

private CardsViewAdapter mAdapter; use this to initialize adapter.

 public class Resume_game_new extends AppCompatActivity {

        private RecyclerView mRecyclerView;
        private CardsViewAdapter  mAdapter;
        private RecyclerView.LayoutManager mLayoutManager;
        List<Game> mDataset;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_resume_game_new);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

            mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view_resume_game);

            // use this setting to improve performance if you know that changes
            // in content do not change the layout size of the RecyclerView
            mRecyclerView.setHasFixedSize(true);

            // use a linear layout manager
            mLayoutManager = new LinearLayoutManager(this);
            mRecyclerView.setLayoutManager(mLayoutManager);

            // specify an adapter (see also next example)
            mDataset = Data.bdd.getGames();
            mAdapter = new CardsViewAdapter(mDataset);
            mRecyclerView.setAdapter(mAdapter);

            //Swipe to Delete
            ItemTouchHelper swipeToDismissTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
                    ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
                @Override
                public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                    return false;
                }

                @Override
                public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
                {

                    // Do Stuff
                    TextView textView_id_game = (TextView) viewHolder.itemView.findViewById(R.id.textView16);
                    Data.bdd.remove_game(Integer.parseInt(textView_id_game.getText().toString()));
                    mDataset.remove(viewHolder.getAdapterPosition());


                    mRecyclerView.removeViewAt(viewHolder.getAdapterPosition());
                    mAdapter.notifyItemRemoved(viewHolder.getLayoutPosition());
                    mAdapter.notifyItemRangeChanged(viewHolder.getAdapterPosition(), mDataset.size());
                    mAdapter.notifyDataSetChanged();

                }

            });
            swipeToDismissTouchHelper.attachToRecyclerView(mRecyclerView);
        }

    }
santosh kumar
  • 2,612
  • 1
  • 12
  • 24