An unordered RecycleView list after scrolling

自作多情 提交于 2020-06-29 04:08:24

问题


If I scroll this list RecycleView with the mouse wheel my items in the list look like unordered. I do not understand , why?

An incorrect clicked item in the new activity from RecycleView

I have tried to create the separate class CrimeAdapter extends RecyclerView.Adapter<CrimeAdapter.CrimeHolder> and class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener in the separate file, but I couldn't do it right. Unfornuntely, I do not have enough experience for this.

I do not know how to write the correct code in the method public void onClick(View v)

Crime.java

package com.bignerdranch.android.criminalintent;

import java.util.Date;
import java.util.UUID;

public class Crime{

    private UUID mId;
    private String mTitle;
    private Date mDate;
    private boolean mSolved;
    private boolean mRequiresPolice;

    public Crime() {
        // Generate unique identifier
        this(UUID.randomUUID());
    }

    public Crime(UUID id) {
        mId = id;
        mDate = new Date();
    }

    public UUID getId() {
        return mId;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public Date getDate() {
        return mDate;
    }

    public void setDate(Date date) {
        mDate = date;
    }

    public boolean isSolved() {
        return mSolved;
    }

    public void setSolved(boolean solved) {
        mSolved = solved;
    }

    public boolean isRequiresPolice() {
        return mRequiresPolice;
    }

    public void setRequiresPolice(boolean requiresPolice) {
        mRequiresPolice = requiresPolice;
    }
}

CrimeLab.java

package com.bignerdranch.android.criminalintent;

import android.content.Context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;


public class CrimeLab {

    private static CrimeLab sCrimeLab;
    private List<Crime> mCrimes;

    public static CrimeLab get(Context context) {
        if (sCrimeLab == null) {
            sCrimeLab = new CrimeLab(context);
        }
        return sCrimeLab;
    }

    private CrimeLab(Context context){

        mCrimes = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            Crime crime = new Crime();
            crime.setTitle("Crime #" + i);
            crime.setSolved(i % 2 == 0); 
            if (i % 4 == 0 ) {crime.setRequiresPolice(true);}
            else {crime.setRequiresPolice(false);}
            mCrimes.add(crime);
        }

    }

    public List<Crime> getCrimes() {
        return mCrimes;
    }

    public  Crime getCrime(UUID id){

        for (Crime crime : mCrimes){
            int rez = id.compareTo(crime.getId());
            if (crime.getId().equals(id)){
                return crime;
            }
        }
        return null;
    }

}

CrimeListFragment.java

package com.bignerdranch.android.criminalintent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.LayoutRes;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.Date;
import java.util.List;

public class CrimeListFragment extends Fragment {

    private static final int REQUEST_CRIME = 1;

    private static final int NOT_REQUIRES_POLICE = 0;
    private static final int REQUIRES_POLICE = 1;

    private RecyclerView mCrimeRecyclerView;
    private CrimeAdapter mAdapter;
    private TextView mTitleTextView;
    private TextView mDateTextView;
    private ImageView mSolvedImageView;
    private Button mButtonCallPolice;
    private Crime mCrime;
    private CharSequence mDateFormat;
    private  int layout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_crime_list, container,
                false);
        mCrimeRecyclerView = (RecyclerView) view
                .findViewById(R.id.crime_recycler_view);
        mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        updateUI();
        return view;
    }

    private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener {


         public CrimeHolder(int layout, LayoutInflater inflater, ViewGroup parent ) {


            super(inflater.inflate(layout, parent, false));

            mTitleTextView = (TextView) itemView.findViewById(R.id.crime_title);
            mDateTextView = (TextView) itemView.findViewById(R.id.crime_date);
            mSolvedImageView = (ImageView) itemView.findViewById(R.id.crime_solved);

            if (itemView.findViewById(R.id.call_police)!=null) {
                mButtonCallPolice = (Button) itemView.findViewById(R.id.call_police);
            }

            itemView.setOnClickListener(this);
        }

        public void bind(Crime crime) {

            mCrime = crime;
            mTitleTextView.setText(mCrime.getTitle());
            mDateFormat = DateFormat.format("EEE, MMM dd, yyyy", mCrime.getDate());

            mDateTextView.setText(mDateFormat);
            mSolvedImageView.setVisibility(mCrime.isSolved() ? View.VISIBLE :
                    View.GONE);

            if(mCrime.isRequiresPolice()){
                mButtonCallPolice.setEnabled(true);
            }
        }

        @Override
        public void onClick(View view) {

            Intent intent = CrimePagerActivity.newIntent(getActivity(),
                    CrimeLab.get(requireActivity()).getCrimes().get((getAdapterPosition())).getId());

            startActivityForResult(intent, REQUEST_CRIME);
        }

    }

    private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> {


        private List<Crime> mCrimes;
        public CrimeAdapter(List<Crime> crimes) {
            mCrimes = crimes;
        }

       @Override
        public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            LayoutInflater layoutInflater = LayoutInflater.from(getActivity());

            if (viewType==1) { layout =  R.layout.list_item_crime_police;}

            else {             layout =  R.layout.list_item_crime;       }

            return new CrimeHolder (layout, layoutInflater, parent);

        }

        @Override
        public void onBindViewHolder(CrimeHolder holder, int position) {
            Crime crime = mCrimes.get(position);
            holder.bind(crime);
        }

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


        public int getItemViewType(int position) {

            Crime crime = mCrimes.get(position);

            return (crime.isRequiresPolice()) ? 1 : 0;

        }

    }


    @Override
    public void onResume() {
        super.onResume();
        updateUI();
    }

    private void updateUI() {
        CrimeLab crimeLab = CrimeLab.get(getActivity());
        List<Crime> crimes = crimeLab.getCrimes();
        if (mAdapter == null) {
            mAdapter = new CrimeAdapter(crimes);
            mCrimeRecyclerView.setAdapter(mAdapter);
        } else {

            mAdapter.notifyDataSetChanged();

        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == REQUEST_CRIME) {
            // Обработка результата
        }

    }

    public void returnResult() {
        getActivity().setResult(Activity.RESULT_OK, null);
    }

}

CrimePagerActivity.java

package com.bignerdranch.android.criminalintent;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;

import androidx.viewpager.widget.ViewPager;

import java.util.List;
import java.util.UUID;

public class CrimePagerActivity extends AppCompatActivity {

    private static final String EXTRA_CRIME_ID = "com.bignerdranch.android.criminalintent.crime_id";

    private ViewPager mViewPager;
    private List<Crime> mCrimes;
    MyAdapter mAdapter;

    public static Intent newIntent(Context packageContext, UUID crimeId) {
        Intent intent = new Intent(packageContext, CrimePagerActivity.class);
        intent.putExtra(EXTRA_CRIME_ID, crimeId);
        return intent;
    }

    @Override
    protected void onCreate( Bundle savedInstanceState ) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_crime_pager);

        UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);

        mViewPager = (ViewPager) findViewById(R.id.crime_view_pager);

        mCrimes = CrimeLab.get(this).getCrimes();

        mAdapter = new MyAdapter(getSupportFragmentManager(),mCrimes);
        mViewPager.setAdapter(mAdapter);

        for (int i = 0; i < mCrimes.size(); i++) {
            if (mCrimes.get(i).getId().equals(crimeId)) {
                mViewPager.setCurrentItem(i);
                break;
            }
        }

    }

    public static class MyAdapter extends FragmentStatePagerAdapter {

        private List<Crime> mCrimesCopy;

        public MyAdapter(FragmentManager fm, List<Crime> mCrimesParametr) {
            //super(fm);
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
            this.mCrimesCopy = mCrimesParametr;

        }

        @Override
        public int getCount() {
            return mCrimesCopy.size();
        }

        @Override
        public Fragment getItem(int position) {
            Crime crime = mCrimesCopy.get(position);
            return CrimeFragment.newInstance(crime.getId());
        }
    }
}

fragment_crime_list.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/crime_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

fragment_crime.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    android:orientation="vertical">
    <TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_title_label"/>
    <EditText
        android:id="@+id/crime_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/crime_title_hint"
        android:inputType=""
        android:autofillHints="" />
    <TextView
        style="?android:listSeparatorTextViewStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_details_label"/>
    <Button
        android:id="@+id/crime_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <CheckBox
        android:id="@+id/crime_solved"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/crime_solved_label"/>
</LinearLayout>

list_item_crime_police.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/crime_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:text="@string/crime_title"
        android:textColor="@android:color/black"
        android:textSize="18sp"
        app:layout_constraintEnd_toStartOf="@+id/crime_solved"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/crime_date"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="@string/crime_date"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/crime_solved" />

    <Button
        android:id="@+id/call_police"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="@string/call_police"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/crime_date" />

    <ImageView
        android:id="@+id/crime_solved"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="16dp"
        android:contentDescription="@string/todo"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_solved" />

</androidx.constraintlayout.widget.ConstraintLayout>

list_item_crime.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

        <TextView
            android:id="@+id/crime_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"
            android:text="@string/crime_title"
            android:textColor="@android:color/black"
            android:textSize="18sp"
            app:layout_constraintEnd_toStartOf="@+id/crime_solved"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/crime_date"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:text="@string/crime_date"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/crime_solved" />

        <ImageView
            android:id="@+id/crime_solved"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="16dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_solved"
            android:contentDescription="@string/todo" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_crime_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/crime_view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</androidx.viewpager.widget.ViewPager>

activity_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

回答1:


I think the items in the RecyclerView are unordered because the references for views which are present in your list_item_crime_police.xml or list_item_crime.xml layout file is declared as class members of CrimeListFragment and not inside CrimeHolder class as :

public class CrimeListFragment extends Fragment {

    // your other views and variables related declarations
    // these are problematic declaration that keeps on being reused
    private TextView mTitleTextView;
    private TextView mDateTextView;
    private ImageView mSolvedImageView;
    private Button mButtonCallPolice;
    // your other declarations

    // your other code
}

That's why, the same view instances such as mTitleTextView, mDateTextView, mSolvedImageView, mButtonCallPolice, etc. are being reused for every CrimeHolder instances causing the unordering of the items in the list. Now, in order to fix this problem, you can simply move these lines to code to CrimeHolder class as class variable which would ensures that every new CrimeHolder instance will have separate instances of above-mentioned views as :

private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
         // declare all of them here so there will be unique instances of these views for unique viewholder
         private TextView mTitleTextView;
         private TextView mDateTextView;
         private ImageView mSolvedImageView;
         private Button mButtonCallPolice;

         public CrimeHolder(int layout, LayoutInflater inflater, ViewGroup parent ) {

            View itemView = inflater.inflate(layout, parent, false));
            super(itemView);

            mTitleTextView = (TextView) itemView.findViewById(R.id.crime_title);
            mDateTextView = (TextView) itemView.findViewById(R.id.crime_date);
            mSolvedImageView = (ImageView) itemView.findViewById(R.id.crime_solved);

            if (itemView.findViewById(R.id.call_police)!=null) {
                mButtonCallPolice = (Button) itemView.findViewById(R.id.call_police);
            }

            itemView.setOnClickListener(this);
        }

        public void bind(Crime crime) {

            mCrime = crime;
            mTitleTextView.setText(mCrime.getTitle());
            mDateFormat = DateFormat.format("EEE, MMM dd, yyyy", mCrime.getDate());

            mDateTextView.setText(mDateFormat);
            mSolvedImageView.setVisibility(mCrime.isSolved() ? View.VISIBLE :
                    View.GONE);

            if(mCrime.isRequiresPolice()){
                mButtonCallPolice.setEnabled(true);
            }
        }

        @Override
        public void onClick(View view) {

            Intent intent = CrimePagerActivity.newIntent(getActivity(),
                    CrimeLab.get(requireActivity()).getCrimes().get((getAdapterPosition())).getId());

            startActivityForResult(intent, REQUEST_CRIME);
        }

    }  

It fixed my problem and I hope it will fix yours too.



来源:https://stackoverflow.com/questions/62285239/an-unordered-recycleview-list-after-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!