In the activation, the next command was nailed to the button (to the usual button), when called, the data will be taken and saved to the "Favorites".

Favorites.addFavorite(Streamer.getInstance().getStation().getStationUrl()); 

next placed the same button, but only to remove the station from the favorites.

 Favorites.removeFavorite(Streamer.getInstance().getStation().getStationUrl()); 

class itself

 public class Favorites { private static List<String> favoriteUrls = null; private static File getFavoritesPath() { return new File(CacheManager.getRoot(), "favorites"); } public static void load() { Sack.open(String[].class, getFavoritesPath()).load(new Sack.Listener<String[]>() { @Override public void onResult(final Sack.Status status, final String[] favorites) { favoriteUrls = new ArrayList<String>(); if (favorites == null) return; for (String favorite : favorites) favoriteUrls.add(favorite); } }); } public static List<Station> getFavorites() { final List<Station> favorites = new ArrayList<>(); for (String url : favoriteUrls) favorites.add(Directory.getStation(url)); Station.sort(favorites); return favorites; } public static void addFavorite(final String favoriteUrl) { if (!favoriteUrls.contains(favoriteUrl)) { favoriteUrls.add(favoriteUrl); commit(); } } public static void removeFavorite(final String favoriteUrl) { if (favoriteUrls.contains(favoriteUrl)) { favoriteUrls.remove(favoriteUrl); commit(); } } protected static void commit() { final String[] urls = favoriteUrls.toArray(new String[favoriteUrls.size()]); Sack.open(String[].class, getFavoritesPath()).commit(urls); } } 

The question is: How to check whether an object is added to favorites or not, and to show the right button right away, either for deletion or for adding to an object as a favorite.

Because the two buttons Add to Favorites and Remove from Favorites in one place, this is not entirely correct and expedient. Thanks in advance for your help!.

  • It is best not to select a separate collection as a favorite, and in the data model that is stored in the general collection, add a flag (Boolean variable) to the favorite. Then you can get your favorites simply by selecting values ​​for this flag, and check in your favorites or not with a simple if. Accordingly, from the content to show the desired button. In the current implementation, the algorithm will be extremely inefficient, since you have no choice but to check each element of the main collection to see if it contains the same value in the favorites collection. - pavlofff
  • @pavlofff, So I do not check every element of the main collection. I appeal only to the collection of favorites itself, to see if there is a required object in it. Checking whether or not there is an object in the chosen one does not occur for all objects, but only for the one that is currently being used (reproducible station) - Anton
  • Made the following method: public static void checkFavorite (final String favoriteUrl) {if (favoriteUrls.contains (favoriteUrl)) {PlayerView.favoriteAdd.setVisibility (View.GONE); PlayerView.favoriteDelete.setVisibility (View.VISIBLE); } else {PlayerView.favoriteAdd.setVisibility (View.VISIBLE); PlayerView.favoriteDelete.setVisibility (View.GONE); } - Anton
  • @pavlofff, I don’t know if I made it right at all, but to check it, it checks and hides the view as expected - Anton
  • because of the wrong organization, you search for a match across the entire collection every time β€” this is very inefficient and takes a lot of resources, while it is possible to store a sign (flag) for each station β€” whether it is selected or not and no separate collection of favorites at all need and no sorting through the collection is also not necessary. - pavlofff 2:53 pm

1 answer 1

To better address your issue, you need to completely rethink the structure of your project. So, it is not very efficient to save favorites to a separate list, since finding out if an item is selected or not is an unreasonable amount of a resource. Also, making two separate buttons to add to favorites, or delete from it - hiding one and showing the other, is also very inefficient.

I offer a more optimal solution.
First, get rid of a separate list of favorites by adding a state flag (boolean) to the model of the main list item - in the selected item or not. This will greatly reduce the resource consumption and greatly simplify the logic.
Secondly, instead of two buttons hiding in turn, use one in which to change the text depending on the current state of the element.

I propose a simple code that implements these ideas, based on the ObjectBox database for example (how to connect to the project ). If you wish, you can easily modify it to fit your data storage structure.
For example, we have a list of some stations (for simplicity, only the fields with the names of stations are filled in), and below the list is a selector button, a successive click on which switches the view to all stations, or to only selected stations. At each station point there is a button, clicking on which either adds the station to the favorites (if it is not there), or removes it from the favorites (if it was there). Comments in the code should clarify the main points of the logic of work.

First, create a data model for ObjectBox (standard POJO with getters / setters):

 @Entity public class Station { @Id long id; String Name; String url; boolean favorite; public Station() { } public Station(String name) { Name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return Name; } public void setName(String name) { Name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public boolean isFavorite() { return favorite; } public void setFavorite(boolean favorite) { this.favorite = favorite; } } 

note: the model class for ObjectBox must contain a field annotated with @id and a constructor with no arguments.

Activi class where all the magic happens:

 public class MainActivity extends AppCompatActivity { String [] stations = {"Station1","Station2","Station3","Station4","Station5","Station6","Station7","Station8","Station9"}; BoxStore boxStore; Box<Station> stationsBox; StationAdapter adapter; Button buttonSelect; boolean onlyFavorite; // ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ вСсь список ΠΈΠ»ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ΅ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); boxStore = MyObjectBox.builder().androidContext(this).build(); stationsBox = boxStore.boxFor(Station.class); if (stationsBox.getAll().isEmpty()) { // Ссли Π±Π°Π·Π° Π½Π΅ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π°, Ρ‚ΠΎ заполняСм Π΄Π°Π½Π½Ρ‹ΠΌΠΈ for(String station:stations){ stationsBox.put(new Station(station)); } } buttonSelect = findViewById(R.id.buttonSelect); RecyclerView rv = findViewById(R.id.list); buttonSelect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ всСго списка ΠΈΠ»ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ onlyFavorite = !onlyFavorite; String textButton = onlyFavorite? "All Station": "Only favorite station"; buttonSelect.setText(textButton); //обновляСм список getDataset(onlyFavorite); } }); rv.setHasFixedSize(true); rv.setLayoutManager(new LinearLayoutManager(this)); ArrayList<Station> dataset = getDataset(onlyFavorite); adapter = new StationAdapter(dataset); rv.setAdapter(adapter); } private ArrayList<Station> getDataset(boolean onlyFavorite) { // Π΄Π΅Π»Π°Π΅ΠΌ Π²Ρ‹Π±ΠΎΡ€ΠΊΡƒ Π² Π‘Π”. ΠŸΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ всС станции ΠΈΠ»ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ·Π±Ρ€Π°Π½Π½Ρ‹Π΅ ArrayList<Station> dataset = (ArrayList<Station>) (onlyFavorite? stationsBox.query().equal(Station_.favorite, true).build().find(): stationsBox.getAll()); //обновляСм список if (adapter != null) adapter.notifyList(dataset); return dataset; } public void onClickFavorite(View view){ // здСсь ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ ΠΊΠ»ΠΈΠΊ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΠ΅ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ Π² Π°ΠΉΡ‚Π΅ΠΌΠ΅ списка // ΠΌΠ΅Ρ‚ΠΎΠ΄ вызываСтся ΠΏΠΎ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρƒ android:onClick xml-Ρ€Π°Π·ΠΌΠ΅Ρ‚ΠΊΠΈ Π°ΠΉΡ‚Π΅ΠΌΠ° // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ID станции, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΊΠ»ΠΈΠΊΠ½ΡƒΠ»ΠΈ ΠΊΠ½ΠΎΠΏΠΊΡƒ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ long id = (long) view.getTag(); // ΠΈΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΊΡƒ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ Station station = stationsBox.get(id); station.setFavorite(!station.isFavorite()); stationsBox.put(station); //обновляСм список getDataset(onlyFavorite); } @Override protected void onStop() { super.onStop(); boxStore.close(); } } 

note: when using the ObjectBox, in order for the MyObjectBox class not to show an error, you need to crash the project (Build -> rebuild project), since this is an auto-generated class and to create it you need to build a project.

Adapter for listing:

 public class StationAdapter extends RecyclerView.Adapter<StationAdapter.ViewHolder>{ ArrayList<Station> stations; public StationAdapter(ArrayList<Station> stations) { this.stations = stations; } @Override public StationAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false)); } @Override public void onBindViewHolder(StationAdapter.ViewHolder holder, int position) { Station station = stations.get(position); holder.name.setText(station.getName()); // Надпись Π½Π° ΠΊΠ½ΠΎΠΏΠΊΠ΅ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ // Если Π½Π΅ Π² ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠΌ, Ρ‚ΠΎ "Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ". Если Π² ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠΌ, Ρ‚ΠΎ "ΡƒΠ±Ρ€Π°Ρ‚ΡŒ" String buttonText = station.isFavorite()? "Delete favorite": "Add favorite"; holder.buttonFavorite.setText(buttonText); // отправляСм Π² Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ‚ΠΈ ID станции, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π½Π°ΠΆΠ°Π»ΠΈ ΠΊΠ½ΠΎΠΏΠΊΡƒ ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ holder.buttonFavorite.setTag(station.getId()); } @Override public int getItemCount() { return stations.size(); } public void notifyList(ArrayList<Station> stations){ this.stations = stations; notifyDataSetChanged(); } public class ViewHolder extends RecyclerView.ViewHolder { final TextView name; final Button buttonFavorite; ViewHolder(View view){ super(view); name = view.findViewById(R.id.name); buttonFavorite = view.findViewById(R.id.buttonFavorite); } } } 

note: to communicate with the activation at the press of a button, the listener assigned in the xml markup of the item through the android:onClick attribute android:onClick - this method works only in activation and does not work in fragments. Other ways to handle click in RecyclerView

Item Marking:

 <android.support.constraint.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:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp"> <TextView android:id="@+id/name" android:layout_width="0dp" android:layout_height="wrap_content" android:paddingLeft="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/buttonFavorite" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="Station" /> <Button android:id="@+id/buttonFavorite" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onClickFavorite" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="Add favorite" /> </android.support.constraint.ConstraintLayout> 

All project on github

  • Comments are not intended for extended discussion; conversation moved to chat . - Yuriy SPb ♦