在RecyclerView中显示多个数据时出现java.lang.IndexOutOfBoundsException

Sea*_*Lab 5 java android android-recyclerview

我将 3 部分数据显示在其中RecyclerView

  1. storyList
  2. yukulList
  3. homeList

当我尝试仅显示storyList或中yukulListhomeList数据时RecyclerView,它有效。但是当我尝试显示多个数据时,例如:storyList && yukulListor storyList && yukulList && homeList,它会显示

java.lang.IndexOutOfBoundsException

我尝试过添加notifyDataSetChanged(),但无法成功。

显示收藏夹列表.java

public class ShowFavouriteList extends AppCompatActivity implements AdapterFavList.FavListener {

    private RecyclerView recyclerView;
    private TextView noFavtsTV;
    AppPreferences appPreferences;
    private SearchView searchView;
    private AdapterFavList yAdapterFavlist;
    private AdapterFavList mAdapterFavlist;
    private AdapterFavList tAdapterFavlist;


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

        SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh);
        pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                finish();
                startActivity(getIntent());
            }
        });

        //toolbar logo and desc
        Toolbar topToolBar = (Toolbar) findViewById(R.id.toolbarTidur);
        setSupportActionBar(topToolBar); //munculkan menu ke toolbar
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); //this line shows back button

        recyclerView = findViewById(R.id.recycler_view);
        noFavtsTV = findViewById(R.id.no_favt_text);

        SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("MyPref", 0);
        SharedPreferences sPTuru = getApplicationContext().getSharedPreferences("MyTuru", 0);
        SharedPreferences sPHome = getApplicationContext().getSharedPreferences("MyHome", 0);
        PreferenceMenejer preferenceMenejer = new PreferenceMenejer(sharedPreferences, sPTuru, sPHome);
        appPreferences = new AppPreferences(preferenceMenejer);

        fetchData();

    } // Oncreate

    private void fetchData() {
        List<Story> storyList = appPreferences.getFavouriteCardList();
        List<YukulModel> yukulList = appPreferences.getFavouriteYukul();
        List<HomeModel> homeList = appPreferences.getFavouriteHome();

        if(storyList != null && storyList.size() > 0) {
            showNoFavtText(false);
            recyclerView.setHasFixedSize(true);
            recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
            tAdapterFavlist = new AdapterFavList(this, storyList, yukulList, homeList, this, appPreferences);
            recyclerView.setAdapter(tAdapterFavlist);
            tAdapterFavlist.notifyDataSetChanged();
        }

        if(yukulList != null && yukulList.size() > 0) {
            showNoFavtText(false);
            recyclerView.setHasFixedSize(true);
            recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
            yAdapterFavlist = new AdapterFavList(this, storyList, yukulList, homeList, this, appPreferences);
            recyclerView.setAdapter(yAdapterFavlist);
            yAdapterFavlist.notifyDataSetChanged();
        }

        if(homeList != null && homeList.size() > 0) {
            showNoFavtText(false);
            recyclerView.setHasFixedSize(true);
            recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
            mAdapterFavlist = new AdapterFavList(this, storyList, yukulList, homeList, this, appPreferences);
            recyclerView.setAdapter(mAdapterFavlist);
            mAdapterFavlist.notifyDataSetChanged();
        }
    }

    @Override
    public void onItemKlik(RecyclerView.ViewHolder viewHolder, HomeModel modelField, int position) {
        // Tidur List
        List<HomeModel> modelList = appPreferences.getFavouriteHome();

            HomeModel click = modelList.get(position);
            Toast.makeText(getApplicationContext(), "Selected: " + click.getName(), Toast.LENGTH_LONG).show();
            int id = Integer.parseInt(click.getIdStory());

            if (id == 0) {
                startActivity(new Intent(this, DoaPagi.class));
            } else if (id == 1) {
                startActivity(new Intent(this, DoaSore.class));
            } else if (id == 2) {
                startActivity(new Intent(this, DoaWc.class));
            } else if (id == 3) {
                startActivity(new Intent(this, DoaMasjid.class));
            } else if (id == 4) {
                startActivity(new Intent(this, DzikirShalat.class));
            } else if (id == 5) {
                startActivity(new Intent(this, ChildYukul.class));
            } else if (id == 6) {
                startActivity(new Intent(this, DoaPakaian.class));
            } else if (id == 7) {
                startActivity(new Intent(this, ChildTidur.class));
            }
    }

    @Override
    public void onItemTuru(RecyclerView.ViewHolder viewHolder, Story tField, int position) {
        // Tidur List
        List<Story> storyList = appPreferences.getFavouriteCardList();

            Story clic = storyList.get(position);
            int idTuru = Integer.parseInt(clic.getIdStory());

            if (idTuru == 0) {
                startActivity(new Intent(this, DoaMauTidur.class));
            } else if (idTuru == 1) {
                startActivity(new Intent(this, DoaBangunt.class));
            } else if (idTuru == 2) {
                startActivity(new Intent(this, DoaJimak.class));
            }
    }

    @Override
    public void onItemYukul(RecyclerView.ViewHolder viewHolder, YukulModel yField, int position) {
        // Tidur List
    }

    private void showNoFavtText(boolean show) {
        noFavtsTV.setVisibility(show ? View.VISIBLE : View.GONE); //jika data yang ditampilkan tidak ada, maka show noFavsTv
        recyclerView.setVisibility(show ? View.GONE : View.VISIBLE); //jika data yang ditampilkan tidak ada, maka don't show rV
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_fav, menu);
        getMenuInflater().inflate(R.menu.menu_main, menu);

        // Associate searchable_tidur configuration with the SearchView
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        searchView = (SearchView) menu.findItem(R.id.action_search_fav).getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setMaxWidth(Integer.MAX_VALUE);

        // listening to search query text change
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                // filter recycler view when query submitted
                mAdapterFavlist.getFilter().filter(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                // filter recycler view when text is changed
                mAdapterFavlist.getFilter().filter(query);
                return false;
            }
        });
        return true;
    }

    // Agar back button pada halaman induk settings berfungsi
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.search_fav) {
            return true;
        }

        switch (item.getItemId()) {
            case android.R.id.home:
                this.finish();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

AdapterFavList.java

public class AdapterFavList extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {

    public static final String ACTION_LIKE_IMAGE_CLICKED = "action_like_image_button";

    final int VIEW_TYPE_TIDUR = 0;
    final int VIEW_TYPE_YUKUL = 1;
    final int VIEW_TYPE_HOME = 2;

    private Context context;
    private AppPreferences appPreferences;
    private List<Story> storyList;
    private List<YukulModel> yukulList;
    private List<HomeModel> homeList;
    private List<HomeModel> homeListFiltered;
    private List<Object> collection = new ArrayList<Object>();
    private FavListener listener;

    private int changedItemPosition;
    private boolean isLiked;

    public AdapterFavList(Context context, List<Story> storyList, List<YukulModel> yukulList, List<HomeModel> homeList, FavListener listener, AppPreferences appPreferences) {

        this.context = context;
        this.storyList = storyList;
        this.yukulList = yukulList;
        this.homeListFiltered = homeList;
        this.listener = listener;
        this.appPreferences = appPreferences;

        addData();
    }

    public void addData() {
        storyList = appPreferences.getFavouriteCardList();
        yukulList = appPreferences.getFavouriteYukul();
        homeList = appPreferences.getFavouriteHome();

        if(storyList != null && storyList.size() > 0) {
            collection.addAll(storyList);
        }

        if(yukulList != null && yukulList.size() > 0) {
            collection.addAll(yukulList);
        }

        if(homeList != null && homeList.size() > 0) {
            collection.addAll(homeListFiltered);
        }
    }

    public interface FavListener {
        void onItemKlik(RecyclerView.ViewHolder viewHolder, HomeModel modelField, int position);
        void onItemTuru(RecyclerView.ViewHolder viewHolder, Story tField, int position);
        void onItemYukul(RecyclerView.ViewHolder viewHolder, YukulModel yField, int position);
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if(viewType == VIEW_TYPE_TIDUR) {
            return new tidurViewHolder(LayoutInflater.from(context).inflate(R.layout.item_story_favourite_list, parent, false));
        }

        if(viewType == VIEW_TYPE_YUKUL) {
            return new yukulViewHolder(LayoutInflater.from(context).inflate(R.layout.item_favourite_yukul, parent, false));
        }

        if(viewType == VIEW_TYPE_HOME) {
            return new homeViewHolder(LayoutInflater.from(context).inflate(R.layout.item_fav_home, parent, false));
        }

        return null;
    }

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

        Object item = collection.get(position);

        if(holder instanceof tidurViewHolder){
            ((tidurViewHolder) holder).bind(storyList.get(position));
            ((tidurViewHolder) holder).setViewData((Story) item, holder.getAdapterPosition());
        }

        if(holder instanceof yukulViewHolder){
            ((yukulViewHolder) holder).bind(yukulList.get(position));
            ((yukulViewHolder) holder).viewDataYukul((YukulModel) item, holder.getAdapterPosition());
        }

        if(holder instanceof homeViewHolder){
            ((homeViewHolder) holder).bind(homeList.get(position));
            ((homeViewHolder) holder).viewDataHome((HomeModel) item, holder.getAdapterPosition());
        }
    }

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

    @Override
    public int getItemViewType(int position){

        Object item = collection.get(position);

        if(item instanceof Story) {
            return VIEW_TYPE_TIDUR;
        }

        if(item instanceof YukulModel){
            return VIEW_TYPE_YUKUL;
        }

        if(item instanceof HomeModel){
            return VIEW_TYPE_HOME;
        }

        return -1;
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();
                List<HomeModel> homeList = appPreferences.getFavouriteHome();
                if (charString.isEmpty()) {
                    homeListFiltered = homeList;
                }
                else {
                    List<HomeModel> filteredList = new ArrayList<>();
                    for (HomeModel row : homeList) {

                        if ( row.getName().toLowerCase().contains(charString.toLowerCase()) ) {
                            filteredList.add(row);
                        }
                    }

                    homeListFiltered = filteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = homeListFiltered;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                homeListFiltered = (ArrayList<HomeModel>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    } //Filter

    public void tidurPutHeart(boolean isChecked, Story tidurstory) {
        SharedPreferences tidursharedPreferences = context.getSharedPreferences("Turu", Activity.MODE_PRIVATE);
        SharedPreferences.Editor tidureditor = tidursharedPreferences.edit();
        tidureditor.putBoolean(tidurstory.getIdStory(), isChecked);
        tidureditor.commit();
    }

    public void yukulPutHeart(boolean isChecked, YukulModel yukulstory) {
        SharedPreferences yukulsharedPreferences = context.getSharedPreferences("Yukul", Activity.MODE_PRIVATE);
        SharedPreferences.Editor yukuleditor = yukulsharedPreferences.edit();
        yukuleditor.putBoolean(yukulstory.getIdStory(), isChecked);
        yukuleditor.commit();
    }

    public void homePutHeart(boolean isChecked, HomeModel homestory) {
        SharedPreferences homesharedPreferences = context.getSharedPreferences("Home", Activity.MODE_PRIVATE);
        SharedPreferences.Editor homeeditor = homesharedPreferences.edit();
        homeeditor.putBoolean(homestory.getIdStory(), isChecked);
        homeeditor.commit();
    }

    //ViewHolder
    public class tidurViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;
        private CheckBox likeCheckBox;

        public tidurViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.text_view);
            likeCheckBox = itemView.findViewById(R.id.like_button_cb);
        } // itemView

        public void bind(final Story item) {
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null){
                        int position = getAdapterPosition();

                        if (position != RecyclerView.NO_POSITION) {
                            listener.onItemTuru(tidurViewHolder.this, item, position);
                        }
                    }
                }
            });
        }

        public void setViewData(final Story story, final int adapterPosition) {

            textView.setText(story.getName());

            if (story.getIsLiked() == 1) {
                likeCheckBox.setChecked(false);
            }
            else {
                likeCheckBox.setChecked(true);
            }

            likeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    changedItemPosition = adapterPosition;

                    if (buttonView.isPressed()) {
                        if (isChecked) {
                            tidurPutHeart(isChecked, story);
                            appPreferences.saveFavouriteCard(story);
                        }
                        else {
                            isLiked = false;
                            tidurPutHeart(isChecked, story);
                            appPreferences.deleteCard(story.getIdStory());
                            // updateLikes();
                            Toast.makeText(context, "Removed", Toast.LENGTH_SHORT).show();

                            if(collection.size() == 0) {
                                ((Activity)context).finish();
                                context.startActivity(((Activity) context).getIntent());
                            }
                        }
                    }
                }
            });

        } //setviewdata

        public void updateLikes() {
            if (!isLiked && storyList.get(changedItemPosition).getIsLiked() == 0) { //jika like dicabut (pada posisi hati yang sedang merah) di halaman favourite list
                storyList.get(changedItemPosition).setIsLiked(0); //maka cabut juga warna merah di halaman favourite list
                notifyItemRangeChanged(getAdapterPosition(), collection.size());
                collection.remove(getAdapterPosition());
                notifyItemRemoved(getAdapterPosition());
            }

        } //updateLikes

    } //tidurViewholder


    //homeViewHolder
    public class homeViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;
        private CheckBox likeCheckBox;

        public homeViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.text_view);
            likeCheckBox = itemView.findViewById(R.id.like_button_cb);
        } // itemView

        public void bind(final HomeModel item) {
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null){
                        int position = getAdapterPosition();

                        if (position != RecyclerView.NO_POSITION) {
                            listener.onItemKlik(homeViewHolder.this, item, position);
                        }
                    }
                }
            });
        }

        public void viewDataHome(final HomeModel story, final int adapterPosition) {

            textView.setText(story.getName());

            if (story.getIsLiked() == 1) {
                likeCheckBox.setChecked(false);
            }
            else {
                likeCheckBox.setChecked(true);
            }

            likeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    changedItemPosition = adapterPosition;

                    if (buttonView.isPressed()) {
                        if (isChecked) {
                            homePutHeart(isChecked, story);
                            appPreferences.saveFavouriteHome(story);
                        }
                        else {
                            isLiked = false;
                            homePutHeart(isChecked, story);
                            appPreferences.deleteCardHome(story.getIdStory());
                    

Ben*_* P. 1

在您的适配器中,该collection列表是唯一可以使用 安全访问的列表position。尝试调用yukulList.get(position)保证最终会抛出异常。

所有这些行onBindViewHolder()都是不安全的,应该更改:

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    // ...
        ((tidurViewHolder) holder).bind(storyList.get(position));
    // ...
        ((yukulViewHolder) holder).bind(yukulList.get(position));
    // ...
        ((homeViewHolder) holder).bind(homeList.get(position));
    // ...
}
Run Code Online (Sandbox Code Playgroud)

getItemViewType()您可以访问通过调用返回的“视图类型”值holder.getItemViewType(),并且可以使用该值来确定要使用的视图持有者和项目的正确类型:

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    Object item = collection.get(position);
    int adapterPosition = holder.getAdapterPosition();

    if (holder.getItemViewType() == VIEW_TYPE_TIDUR){
        Story story = (Story) item;
        tidurViewHolder vh = (tidurViewHolder) holder;
        vh.bind(story);
        vh.setViewData(story, adapterPosition);
    } else if (holder.getItemViewType() == VIEW_TYPE_YUKUL){
        YukulModel yukul = (YukulModel) item;
        yukulViewHolder vh = (yukulViewHolder) holder;
        vh.bind(yukul);
        vh.viewDataYukul(yukul, adapterPosition);
    } else if (holder.getItemViewType() == VIEW_TYPE_HOME){
        HomeModel home = (HomeModel) item;
        homeViewHolder vh = (homeViewHolder) holder;
        vh.bind(home);
        vh.viewDataHome(home, adapterPosition);
    }
}
Run Code Online (Sandbox Code Playgroud)

另请注意,无需实际传递holder.getAdapterPosition()到 eg setViewData(),因为您可以简单地getAdapterPosition()tidurViewHolder方法内调用。

我还想说,您可以将您的bind()setViewData()调用合并为一个,这将使您得到以下结果:

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    Object item = collection.get(position);

    if (holder.getItemViewType() == VIEW_TYPE_TIDUR){
        ((tidurViewHolder) holder).bind((Story) item);
    } else if (holder.getItemViewType() == VIEW_TYPE_YUKUL){
        ((yukulViewHolder) holder).bind((YukulModel) item);
    } else if (holder.getItemViewType() == VIEW_TYPE_HOME){
        ((homeViewHolder) holder).bind((HomeModel) item);
    }
}
Run Code Online (Sandbox Code Playgroud)