First fragment
private void initRecyclerView() {
Main.musicList = Main.songs.songs;
if ((Main.musicList != null) && (!Main.musicList.isEmpty())) {
// Connects the song list to an adapter
// (Creates several Layouts from the song list)
allSongsAdapter = new AllSongsAdapter(getActivity(), Main.musicList);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerViewSongs.setLayoutManager(linearLayoutManager);
recyclerViewSongs.setHasFixedSize(true);
recyclerViewSongs.setAdapter(allSongsAdapter);
}
}
In the first fragment i have a recyclerview which displays a list with all songs found on the device and i have an option to delete a song which changes the data in my arraylist Main.musicList by rescanning all songs on the device.
So all my other arraylists in my app still have a reference to that deleted song.
So how can i call notifySetDataChanged on all recyclerview adapters in other fragments when i delete an item in the first fragment?
Use ViewModel in your Activity which holds these fragments.
Wrap your song list in LiveData object. This can be observed by all
of your fragments depending on their lifecycle (when the fragment is
in OnResumed state, it will be automatically notified when your list
has changed)
In related fragment start to observe LiveData and on
change update your adapter.
Related topics:
https://developer.android.com/topic/libraries/architecture/livedata
https://medium.com/androiddevelopers/viewmodels-and-livedata-patterns-antipatterns-21efaef74a54
Hope I could help you.
The easy way will be to use BroadcastReceiver. try this answer
You can use EventBus to trigger the method, by which reyclcer view adapter will be notified
Related
Currently working on recyclerview that refreshes every time I choose something.
Everytime I would set again the adapter after I selected a choice.
For example, if I choose Fruit, the recyclerview will change to fruits.
I would attach a new adapter to the recyclerview everytime.
The problem with this is whenever I check on onViewScrolled, it is getting called the same amount as I changed the recyclerview data.
My question is, why does this occurs ? Is it because the old adapter didn't detach ?
If yes, how do I detach it properly ?
I think you have a problem with the recycler adapter class. For example, you change some data and scroll down. When your scroll is up and that shows your old data.
Add this code in the adapter class.
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
I am new to android and I am having a problem reloading (rebuilding) as recyclerview after the activity is active. The activity with the recyclerview is a second activity started as an intent on the main activity. I can load it up, and show a list of items. When one of the items is clicked a third activity is launched. The problem is sometimes there are too many items on the list. I want to add a way of selecting an item more easily. I added a spinner on the same activity as the recyclerview. When an item is selected on the spinner, I want to reload a shorter version of the list, based on the spinner selection. However, I can't find a way to achieve that. Any help or suggestions pointing me in the right direction will be greatly appreciated.
as #bink said without code it's hard to help, but the idea in general is that on your spinner.setOnItemSelectedListener() you populate your recyclerView, so everytime you change the selection you get a new list depending on the choosed value.
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
ArrayList<> arrayList = new ArrayList<>();
// add your items based on item spinner.itemSelected
// for(---)
adapter = new MyAdapter(context, arrayList );
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
});
You can also add a filter to your recycler view (https://medium.com/android-news/filterable-recyclerview-in-android-the-how-to-a9ade9cd26)
If you dont want to recreate all the recycler view and the list itselft, use adapter.notifyDataSetChanged();
I'm kinda new to Android developpement and I use the 'Navigation' library.
Starting from my first fragment (which is a recyclerview that fetch data from an API), if I navigate to another fragment, the navigation controller destroy the first fragment and create the second fragment and show it. If I want to return to the first one (with the left arrow or the back button), it destroy de second fragment and create the first from scratch, making it reload all the data and using bandwith.
I have read many solutions for this but they are all fastidious :
using mvvm
write my own navigation controller
using mvp
I'd like to know what's the better way to retrieve data back without calling again my API.
My first fragment :
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AnnoncesViewModel annoncesViewModel = new ViewModelProvider(this).get(AnnoncesViewModel.class);
root = inflater.inflate(R.layout.fragment_annonces, container, false);
ctx = root.getContext();
recyclerView = root.findViewById(R.id.listeannonce_rv);
annoncesViewModel.getAnnonces().observe(this, data-> {
recyclerViewAdapter = new ListeAnnoncesAdapter(data, ctx, AnnoncesFragment.this);
recyclerView.setLayoutManager(new LinearLayoutManager(root.getContext()));
recyclerView.setAdapter(recyclerViewAdapter);
});
return root;
}
The viewmodel :
public class AnnoncesViewModel extends ViewModel {
MutableLiveData<ArrayList<Annonce>> annonces;
ArrayList<Annonce> AnnonceArrayList;
public AnnoncesViewModel() {
annonces = new MutableLiveData<>();
AnnonceArrayList = new ArrayList<>();
annonces.setValue(AnnonceArrayList);
}
public MutableLiveData<ArrayList<Annonce>> getAnnonces() {
return annonces;
}
}
For navigation, i use
navController.navigate(R.id.frag1_to_frag2);
or
navController.navigate(R.id.nav_frag2);
But it doesn't change anything.
At the moment, the data is retrieved when I press a button.
Thanks for help !
The ViewModel approach is the right choice. The problem is that when you navigate to the new fragment, the AnnoncesViewModel is getting destroyed also because you are passing the Fragment context to the ViewModelProvider. To keep the ViewModel after navigating to other fragment pass Activity context to the the provider like:
ViewModelProviders.of(requireActivity()).get(AnnoncesViewModel::class.java)
This will keep the ViewModel "alive" when you launch again your Fragment instead of creating a new AnnoncesViewModel every time the Fragment is created.
I'm using a Master / Detail flow (not the default one), so I have one fragment that contains the stuff of the RecyclerView and when I click on a item I see on other fragment the detail of that item, it works, but now I want to delete this item from the detail fragment, and when I click on delete it refreshes and then notifydatasetchanged.
What's the problem? I have the Adapter on my ListFragment and on my DetailFragment I only can delete the item from my SQLite nothing else, I'd like to refresh the list.
Activity -- Where I create the listFragment
Fragment1 -- ListFragment (RecyclerView, Adapter, Sqlite(For fetch products))
Fragment2 -- DetailFragment (Sqlite(to delete item))
Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
if(savedInstanceState == null){
Fragment list = new ListFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().add(R.id.list,list).commit();
}
}
On my ListFragment I have those attributes
private SQLiteAdapter sqliteAdapter;
private Context mContext;
private Adapter adapter;
private RecyclerView recyclerView;
private List<Product> data;
Then I put the data with a method that open the sqliteAdapter and then fetch all products and then closses the connection.
On my DetailFragment I have the SQLite object to get the product sent from the adapter (id product) and then show info about this product.
Now I can delete an object, but it's not refreshing from ListFragment, I'm wondering where to put this SQLite object on Activity or in both fragments is ok
It sounds like you are only deleting the item from your database. You also need to delete it from the adapter's list or other data structure.
I have a RecyclerView which is constructed by inflating CardView Layout. This is acheived by onCreateViewHolder method. I am passing a ArrayList of data to the RecyclerView.
My requirement is, on clicking the list item, I have to load a new page which shows the details of the item clicked. For this, I need to get the id of the item clicked which is not showed in the view. In the view I have only Name and email of the item.
Let's say, the ArrayList I am passing is of type Person and Person has member variables id,name,email,education,location.
In the RecyclerView onBindViewHolderfunction, I am setting only name and email.
I need to get the id of the item, then only I can do a db command and get details of the particular person.
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.recyclerList);
rv.setAdapter(new NGOViewHolder(ArrayList()));
rv.addOnItemTouchListener( // and the click is handled
new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Intent intent = new Intent(getActivity(),NGODetails.class);
intent.putExtra("ID", (IDOfTheItemClicked));
}));
I requirement is IDOfTheItemClicked, that is passing in the above
Intent(getActivity(),NGODetails.class);
intent.putExtra("ID", (IDOfTheItemClicked));
should be the id of the item that is in the ArrayList that I have passed initially.
How can I get to send the id of the Person object which is currently showing in the view, to the next screen, on clicking the list item.
set position for each item using setTag inside onCreateViewHolder method after that when you'll click then inside onclick you get a view reference from there, get that tag and convert to int( this will give you position of view)
onCreateViewHolder(............){
View view;
view.setTag(id, position);
view.setOnTouch or Onclick(View v){
String position = v.getTag(),toString();
// get your id using this position
}
}
If you don't change the order of the items in your adapter, simply call yourArrayList.get(position).yourgetIDOfTheItemClickedMethod in the onClick.