I´m working on a project where I´m trying to add an options filter. For more individual results I started to implement an options filter which gives a user the ability to choose their prefered options and got individual results displayed in a paged recyclerview. First I started to use relative layouts with checkboxes inside and a text view which shows the number of results a user gets for a certain option.
Cause there were to many views in my layout I switched to a custom recycler list view which displays the option items. I gave the user the ability to choose different music genres but cause there are to many genres out there I started to implement a sub recyclerview list for the items of the genre recyclerview list.
The items and sub items should display the number of results which a user got if they choose that option but I got stuck with 500 lines boilerplate and to many web request to get the number of results for each option.
Everything is working fine till I tried to set also counter for the sublist. I didn´t find any better solutions for my problem. I got different models for my recycler and sublist recycler and don´t know how to successfull implement a counter for all categorys and sub categorys.
When I´m trying to implement a counter for the sub categorys the app crashs with the error
java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
at java.util.ArrayList.get(ArrayList.java:437)
at
de.n.UI.Fragments.Config.Config_Filter.lambda$filtercount$14$Config_Filter(Config_Filter.java:305)`
I set the counter for the sub categorys on that way:
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Dance))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(0, new FilterItem(filterItems.get(0).state, filterItems.get(0).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Disco))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(1, new FilterItem(filterItems.get(1).state, filterItems.get(1).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Pop))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(2, new FilterItem(filterItems.get(2).state, filterItems.get(2).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.RNB))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(3, new FilterItem(filterItems.get(3).state, filterItems.get(3).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Club))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(4, new FilterItem(filterItems.get(4).state, filterItems.get(4).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Retro))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(5, new FilterItem(filterItems.get(5).state, filterItems.get(5).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Schlager))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItemsMainstream.set(6, new FilterItem(filterItems.get(6).state, filterItems.get(6).ItemName, integer));
filterSubItems.set(0, new FilterSubItem(filterItemsMainstream, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
But everytime I started it once again its shows me a out of bounds
at a new line I think its because to many web requests or to much new arrays or something like that.
A short version of my code without the web requests for the sublist:
public class Config_Filter extends DialogFragment implements FilterItemInterface {
FilterItem filterItem;
ArrayList<FilterItem> filterItems, filterItemsMainstream, filterItemsHipHop, filterItemsTechno, filterItemsRock, filterItemsSprache, filterItemsSonstig;
ArrayList<FilterSubItem> filterSubItems;
Bundle filterbundle;
FilterStates filterStates;
String adress;
MainViewModel viewModel;
LocationViewModel locationViewModel;
private final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
ArrayList<String> Genre, Art, Extra;
int radius = 25, age, privat, StartPrice, EndPrice;
String starttime, endtime;
FilterListAdapter filterListRecycler;
double lat, lng;
public String Date;
public static final String TAG = "config_dialog";
FragmentConfigBinding binding;
@Override
public void onStart() {
super.onStart();
//dialog settings
Dialog dialog = getDialog();
if (dialog != null) {
int width = ViewGroup.MarginLayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width, height);
ColorDrawable back = new ColorDrawable(Color.TRANSPARENT);
InsetDrawable inset = new InsetDrawable(back, 0, 60, 0, 0);
dialog.getWindow().setBackgroundDrawable(inset);
dialog.getWindow().setWindowAnimations(R.style.AppTheme_Slide);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
setStyle(DialogFragment.STYLE_NO_FRAME, R.style.AppTheme_FullScreenDialog);
super.onCreate(savedInstanceState);
//current adress of user and lat and lng to get location oriented results
lat = requireArguments().getDouble(Config.KEY_EMP_LAT);
lng = requireArguments().getDouble(Config.KEY_EMP_LNG);
}
@SuppressLint({"SetTextI18n", "DefaultLocale"})
@Override
public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
binding = FragmentConfigBinding.inflate(inflater, container, false);
//setup ArrayLists
Genre = new ArrayList<>();
Art = new ArrayList<>();
Extra = new ArrayList<>();
filterItems = new ArrayList<>();
filterItemsMainstream = new ArrayList<>();
filterItemsHipHop = new ArrayList<>();
filterItemsTechno = new ArrayList<>();
filterItemsRock = new ArrayList<>();
filterItemsSprache = new ArrayList<>();
filterItemsSonstig = new ArrayList<>();
filterSubItems = new ArrayList<>();
filterartitems();
expandLayout();
return binding.getRoot();
}
public void filterartitems() {
filterSubItems.add(new FilterSubItem(filterItemsMainstream, false, getString(R.string.Mainstream), 0));
filterSubItems.add(new FilterSubItem(filterItemsHipHop, false, getString(R.string.Hip_Hop), 0));
filterSubItems.add(new FilterSubItem(filterItemsTechno, false, getString(R.string.Electro), 0));
filterSubItems.add(new FilterSubItem(filterItemsRock, false, getString(R.string.Rock), 0));
filterSubItems.add(new FilterSubItem(filterItemsSprache, false, getString(R.string.Language), 0));
filterSubItems.add(new FilterSubItem(filterItemsSonstig, false, getString(R.string.Sonstiges), 0));
filterItems.add(new FilterItem(false, getString(R.string.Bar), 0));
filterItems.add(new FilterItem(false, getString(R.string.Club), 0));
filterItems.add(new FilterItem(false, getString(R.string.Festival), 0));
filterItems.add(new FilterItem(false, getString(R.string.OpenAir), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.Dance), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.Disco), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.Pop), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.RNB), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.Club), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.Retro), 0));
filterItemsMainstream.add(new FilterItem(false, getString(R.string.Schlager), 0));
filterItemsHipHop.add(new FilterItem(false, getString(R.string.Rap), 0));
filterItemsHipHop.add(new FilterItem(false, getString(R.string.Drill), 0));
filterItemsHipHop.add(new FilterItem(false, getString(R.string.Trap), 0));
filterItemsHipHop.add(new FilterItem(false, getString(R.string.CloudRap), 0));
filterItemsHipHop.add(new FilterItem(false, getString(R.string.Underground), 0));
filterItemsHipHop.add(new FilterItem(false, getString(R.string.LofiHipHop), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Techno), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.EuroTechno), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.House), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Techhouse), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Fusion), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Trance), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Psychadelic), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Rave), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Goa), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.DrumandBass), 0));
filterItemsTechno.add(new FilterItem(false, getString(R.string.Progressive), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.RockRoll), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.HardRock), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.Metal), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.DeathMetal), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.Punk), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.AcidPunk), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.GothicRock), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.PunkRock), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.ClassicRock), 0));
filterItemsRock.add(new FilterItem(false, getString(R.string.PsychadelicRock), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Balkan), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Latin), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.BootyBass), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Funk), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Samba), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Tango), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Jazz), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.JazzFunk), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.AcidJazz), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Reggae), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Folk), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.PopFunk), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Blues), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Soul), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.RhythmicSoul), 0));
filterItemsSprache.add(new FilterItem(false, getString(R.string.Swing), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Classical), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Oldies), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Alternative), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Ska), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Vocal), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.InstrumentalPop), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Bluegrass), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.Primus), 0));
filterItemsSonstig.add(new FilterItem(false, getString(R.string.SlowJam), 0));
ViewModel();
recycler();
RecyclerAdapter();
}
public void ViewModel() {
viewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
locationViewModel = new ViewModelProvider(requireActivity()).get(LocationViewModel.class);
}
public void recycler() {
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
binding.expandart.setLayoutManager(new LinearLayoutManager(getContext()));
binding.expandgenre.setLayoutManager(new LinearLayoutManager(getContext()));
}
public boolean cleanParams() {
return Art.size() == 0 || Genre.size() == 0 || privat == 0 || age == 0 || radius == 25 || starttime.equals(getString(R.string.start)) || endtime.equals(getString(R.string.end)) || Date.equals(getString(R.string.Datum));
}
public void RecyclerAdapter()
{
FilterGenreListAdapter filterGenreListAdapter=new FilterGenreListAdapter(requireContext(),filterSubItems,this);
filterListRecycler=new FilterListAdapter(filterItems,this);
binding.expandart.setAdapter(filterListRecycler);
binding.expandgenre.setAdapter(filterGenreListAdapter);
filtercount();
}
public void expandLayout()
{
binding.ArtConfig.setOnClickListener(v -> {
if (binding.expandart.getVisibility()==View.GONE) {
expand(binding.expandart);
binding.ArtConfig.setActivated(true);
}
else {
collapse(binding.expandart);
binding.ArtConfig.setActivated(false);
}
});
binding.GenreConfigNew.setOnClickListener(v -> {
if (binding.expandgenre.getVisibility()==View.GONE) {
expand(binding.expandgenre);
binding.GenreConfigNew.setActivated(true);
}
else {
collapse(binding.expandgenre);
binding.GenreConfigNew.setActivated(false);
}
});
}
@Override
public void getFilterItem(FilterItem filterItem) {
}
public static void expand(final View v) {
int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
final int targetHeight = v.getMeasuredHeight();
// Older versions of android (pre API 21) cancel animations for views with a height of 0.
v.getLayoutParams().height = 1;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? LinearLayout.LayoutParams.WRAP_CONTENT
: (int)(targetHeight * interpolatedTime);
v.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// Expansion speed of 1dp/ms
a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation()
{
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
// Collapse speed of 1dp/ms
a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
//count result size for the single options
@SuppressLint("SetTextI18n")
public void filtercount() {
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), new ArrayList<>(Collections.singletonList(getString(R.string.Bar))), Genre, Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItems.set(0, new FilterItem(filterItems.get(0).state, filterItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), new ArrayList<>(Collections.singletonList(getString(R.string.Club))), Genre, Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItems.set(1, new FilterItem(filterItems.get(1).state, filterItems.get(1).ItemName, integer));
filterListRecycler.notifyItemChanged(1);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), new ArrayList<>(Collections.singletonList(getString(R.string.Festival))), Genre, Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItems.set(2, new FilterItem(filterItems.get(2).state, filterItems.get(2).ItemName, integer));
filterListRecycler.notifyItemChanged(2);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), new ArrayList<>(Collections.singletonList(getString(R.string.OpenAir))), Genre, Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterItems.set(3, new FilterItem(filterItems.get(3).state, filterItems.get(3).ItemName, integer));
filterListRecycler.notifyItemChanged(3);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Mainstream))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterSubItems.set(0, new FilterSubItem(filterSubItems.get(0).filterItem, filterSubItems.get(0).state, filterSubItems.get(0).ItemName, integer));
filterListRecycler.notifyItemChanged(0);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Hip_Hop))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterSubItems.set(1, new FilterSubItem(filterSubItems.get(1).filterItem, filterSubItems.get(1).state, filterSubItems.get(1).ItemName, integer));
filterListRecycler.notifyItemChanged(1);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Techno))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterSubItems.set(2, new FilterSubItem(filterSubItems.get(2).filterItem, filterSubItems.get(2).state, filterSubItems.get(2).ItemName, integer));
filterListRecycler.notifyItemChanged(2);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Rock))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterSubItems.set(3, new FilterSubItem(filterSubItems.get(3).filterItem, filterSubItems.get(3).state, filterSubItems.get(3).ItemName, integer));
filterListRecycler.notifyItemChanged(3);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Sprache))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterSubItems.set(4, new FilterSubItem(filterSubItems.get(4).filterItem, filterSubItems.get(4).state, filterSubItems.get(4).ItemName, integer));
filterListRecycler.notifyItemChanged(4);
}
});
viewModel.getFilteredData(lat, lng, firebaseAuth.getUid(), Art, new ArrayList<>(Collections.singletonList(getString(R.string.Sonstiges))), Extra, privat, age, radius, starttime, endtime, StartPrice, EndPrice, Date).observe(getViewLifecycleOwner(), integer -> {
if (integer != null) {
filterSubItems.set(5, new FilterSubItem(filterSubItems.get(5).filterItem, filterSubItems.get(5).state, filterSubItems.get(5).ItemName, integer));
filterListRecycler.notifyItemChanged(5);
}
});
}
}
For the sublist I got another 400 lines like the filtercount. I would be thankful for any help.
Aucun commentaire:
Enregistrer un commentaire