0

i am trying to implement an option to hide certain items from an ArrayList "mTaskList".

For that, i provide a boolean "hideDues" in the Adapter's Constructor. If it is true, i filter these items out of the list.

public DeadlinesAdapter(Context context, ArrayList<TaskItem> taskList, DeadlinesAdapterListener listener, boolean hideDues) {
    if (hideDues) {
        for (int i = 0; i < taskList.size(); i++) {
            if (taskList.get(i).getTimeLeftInMinutes() < 1) taskList.remove(i);
        }
    }
    mTaskList = taskList;
    mContext = context;
    mListener = listener;
}

It works, but when i set that boolean to false and reset the adapter, it still uses the filtered list, even though the original ArrayList i provide in the Constructor, is unchanged.

if (mHideDues) {
                mHideDues = false;
                item.setIcon(R.drawable.ic_invisible_white);
            } else {
                mHideDues = true;
                item.setIcon(R.drawable.ic_visible_white);
            }

            mDeadlinesAdapter = new DeadlinesAdapter(this, mTaskList, this, mHideDues);
            mDeadlinesRecyclerView.setAdapter(mDeadlinesAdapter);

I change the boolean and reset the Adapter. mTaskList shouldnt have any changes. So why doesnt it take a new ArrayList?

  • Have you debugged it? – Sergei Sirik Sep 14 '17 at 19:34
  • Are you re-using the same list that you already removed the items from? Recreating the adapter will not bring those items back. – fweigl Sep 14 '17 at 19:35
  • I checked the boolean with the debugger and its set to false properly. The ArrayList that the Activity provides should be unchanged, because i filter those items out inside the adapter. Or am i mistaken here? – Florian Walther Sep 14 '17 at 19:37
  • 1
    You are mistaken. See [this](https://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html) – Sergei Sirik Sep 14 '17 at 19:41
  • notifyDataSetChanged() doesnt do anything either. – Florian Walther Sep 14 '17 at 19:43
  • @Sergei Sirik Ok i understand, so i have to find another solution. Should i create a new ArrayList inside the Constructor by iteratin through the original list and adding each item individually or how would i get a totaly seperate list? – Florian Walther Sep 14 '17 at 19:44

2 Answers2

3

You have to copy your ArrayList like this for example:

ArrayList newList = new ArrayList(oldList);

And only then pass it to the DeadlinesAdapter. It should solve your problem.

Sergei Sirik
  • 1,249
  • 1
  • 13
  • 28
  • Thank you guys, and sorry for getting such a basic concept wrong. – Florian Walther Sep 14 '17 at 19:50
  • Only problem: Now .notifyDatasetChanged doesnt work anymore. I guess i have to find another solution? I only works if pass the reference and not after adding the items to a new list. – Florian Walther Sep 14 '17 at 20:03
  • Sorry, I'm not quite getting your question. I'm not an android developer, but I assume that .notifyDatasetChanged will work if you change the corresponded Collection(List in this case). So, what are you trying to achieve then: on one hand you don't want to change the initial list, but on the other you want to be notified about what? Probably, you should rethink your app logic or/and post a separate question – Sergei Sirik Sep 14 '17 at 23:38
  • Just an idea/workaround. Copy the list but pass original list to `DeadlinesAdapter`, so this way you will have a copy with the values from the original list, and modified original list. – Sergei Sirik Sep 14 '17 at 23:42
2

Sergei pointed to the problem: You are passing the list of tasks to your adapter, where you filter the list. Now what you probably want to do is filter a copy of the list. What you actually do is remove the items from the original list. That's why when you set mHideDues to false, nothing happens.

What you can do is simply:

ArrayList<TaskItem> mTaskList = new ArrayList<TaskItem>();

public DeadlinesAdapter(Context context, ArrayList<TaskItem> taskList, DeadlinesAdapterListener listener, boolean hideDues) {

    mTaskList.addAll(taskList);

    if (hideDues) {
        for (int i = 0; i < this.list.size(); i++) {
            if (mTaskList.get(i).getTimeLeftInMinutes() < 1) mTaskList.remove(i);
        }
    }

    mContext = context;
    mListener = listener;
}
fjc
  • 5,590
  • 17
  • 36
  • Thank you guys, and sorry for getting such a basic concept wrong. – Florian Walther Sep 14 '17 at 19:50
  • One more question: Does it make a difference performance-wise, if i use .addAll and then filter the list, or if i only the not-to-be-hidden items in the first place? – Florian Walther Sep 14 '17 at 19:51
  • It will make a small difference, which probably will be hardly noticable unless you're moving really large amounts of data. To be elegant, you could use some filter like this: https://stackoverflow.com/questions/122105/what-is-the-best-way-to-filter-a-java-collection – fjc Sep 14 '17 at 19:54
  • Only problem: Now .notifyDatasetChanged doesnt work anymore. I guess i have to find another solution? I only works if pass the reference and not after adding the items to a new list. – Florian Walther Sep 14 '17 at 20:03
  • where/how do you use it? without seeing the code it's hard to tell – fjc Sep 14 '17 at 20:03
  • Well it doesnt work anywhere i use it, if i write mTaskList = new ArrayList<>(); mTaskList.addAll(taskList); instead of mTasklist = taskList – Florian Walther Sep 14 '17 at 20:10
  • Which behavior do you expect and what happens? It maybe makes sense to open a new question on that, though – fjc Sep 14 '17 at 20:11
  • Well i try to give the option to hide certain items from a list. But it seems not possible without managing 2 seperate ArrayLists. – Florian Walther Sep 14 '17 at 20:40
  • yes, notifyDataSetChanged is not a replacement for maintaining your data in a list. – fjc Sep 14 '17 at 20:54