RecyclerView - Access to a list from another class - android

I want to access a list from another class then put it inside my RecyclerViewAdapter object .
The first class which contains the list.
public class Class1 {
// The List :
List<Model1> mlisto = new ArrayList<>();
mlisto.add(new Model1("HOLA","Dep17",R.drawable.img));
mlisto.add(new Model1("bonjour","Dep17",R.drawable.img));
mlisto.add(new Model1("hi","Dep17",R.drawable.img));
}
The second class which access the list from the first class.
public class Class2 {
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this,new Class1().mlisto);
}
When I use new Class1().mlisto it returns nothing like an empty list
and the RecyclerView doesn't show anything on the app.

you can use interfaces
create an interface inside class1 like this:
public interface CustomListListener{
void onListChanged(List<Model1> myList);
}
create a property of listener inside Class1:
CustomListListener mListener;
add a public function for initializing the listener inside Class1:
public static void setOnListChangeListener(CustomListListener listener){
this.mListener = listener;
}
implement the listener inside Class2:
public class Class2 implements Class1.CustomListListener {
}
when you implement listener inside Class2, you will get a function inside class2 like this :
#Override
public void onListChanged(List<Model1> myList) {
// in here you will access the list that you created or changed inside class1
}
when you wanna send the myList data to class2:
1- initiate the mListener property :
for example you can initiate the mListener inside OnCreate Function of class
Class1.setOnListChangeListener(this)
this refers to class2 context
2- send the data to class2
inside your class1, whenever you want to update the list use mListener property like this :
mListener.onListChanged(myList);
this like you can change the list whenever you want and get the updated value inside onListChanged function, also you can add more functions inside your CustomListListener for different scenarios like removing items, adding items and etc...

You can access the list like this :
public class Class1{
private List<Model> mList;
public List<Model1> getList(){
mList = new ArrayList<>();
mList.add(new Model1("HOLA","Dep17",R.drawable.img));
mList.add(new Model1("bonjour","Dep17",R.drawable.img));
mList.add(new Model1("hi","Dep17",R.drawable.img));
return mList
}
}
And in second class, you can use it like this:-
RecyclerViewAdapterrr adapter = new RecyclerViewAdapterrr(this,new Class1().getList());
setAdapter() is important
your_recyclerview_object.setAdapter(adapter);

You can use sharedPreference to store the list and can access it anywhere in your project by using its key. The best approach is shared in this link TinyDb Example

Related

Activity/Fragment and ViewModel in Adapter good practice?

Let's assume that we have Activity/Fragment which contains a RecyclerView. Furthermore, it sets an Adapter. For the sake of the example, let's say the Adapter has to have access to Fragment in order to call a method which displays a Snackbar. Moreover, Let's say there are a couple of items in the adapter. I want to delete one and remove it from the database. Therefore I should call ViewModel's methods. I've made a research but I couldn't find any information if referencing a fragment into the Adapter is good or not.
Could you help me and explain? Also for the ViewModel I've found some ideas here.
But what are the best practices?
good Adapter Classes should be STATIC helping developers to keep it separated from Activity/Fragment part
don't save Activity/Fragment reference inside Adapters
ViewModels should belongs to Activities or Fragments
Adapters should execute Activity/Fragment's actions via Callbacks/Listeners or LiveData
Pseudo-code:
public class MainActivity extends Activity {
private interface Listener {
void OnRemoved(#NonNull xxx removedItem);
}
private static final class MyAdapter extends ArrayAdapter<xxx> {
private final Listener mListener;
private MyAdapter(#NonNull final Listener listener) {
super(...);
this.mListener = listener;
}
#Override
public void remove(xxx item) {
super.remove(xxx); //<-- this removes item from Adapter
this.mListener.OnRemoved(item); //<-- this triggers Activity's code
}
}
public void onCreate(...) {
...
new MyAdapter(new Listener() {
#Override
public void OnRemoved(#NonNull final xxx removedItem) {
Snakbar.makeText(....).show();
}
});
}
}

Wait for ListAdapter to complete so I can apply a filter

Right now, I'm getting some values to fill a recyclerView with the following list adapter through binding:
private val otrosSubmitListAdapter = OtrosSubmitListAdapter()
[more code]
binding.otrosRequestList.adapter = otrosSubmitListAdapter
Problem is that I'd like to, when all values have been binded, merge then with some other values, I'd like to make the merge in a variable called DummyContent.ITEMS, which I would later put a new filterAdapter and use that adapter for my recyclerview, like this:
dataArray = DummyContent.ITEMS
filter_adapter = MyFilterAdapter(this.activity, dataArray)
recyclerView.adapter = filter_adapter
Problem is that I cannot grasp a way for waiting so OtrosSubmitListAdapter() has completed all its internal binding and I can get its values properly, right now by using this code DummyContents have never the values needed from OtrosSubmitListAdapter() to be merged, so only its other values can be properly shown.
What would be a possible way to wait for OtrosSubmitListAdapter() to complete all its binding and getting to properly use the results?
Create a callback inside your OtrosSubmitListAdapter like this:
public interface AdapterCallback {
void itemsBound();
}
Add it to your activity
public class MainActivity extends AppCompatActivity implements AdapterCallback
Pass a reference of AdapterCallback to OtrosSubmitListAdapter when you are initializing it
On your adapter
AdapterCallback adapterCallback;
public OtrosSubmitListAdapter(AdapterCallback adapterCallback){
this.adapterCallback = adapterCallback;
}
#Override
public void onBindViewHolder(final OtrosSubmitListAdapter.MyViewHolder holder, final int position) {
if (position == itemList.size() - 1){
adapterCallback.itemsBound();
}
}
On your activity
private val otrosSubmitListAdapter = OtrosSubmitListAdapter(this)
#Override
public void itemsBound() {
//enter code here
}
see https://stackoverflow.com/a/32032990/11881779 for adapter callback example
Edit : If I understood your question wrong, please share code of your adapter and activity

Passing an argument from a regular class to an activity

I would like to call a method in an activity and pass an argument to it from a non activity regular class in android.
As i understand, i cant simple use the following code, plus it does not work:
int mySound = 0;
SoundsActivity soundsActivity = new SoundsActivity();
soundsActivity.playSound(mySound);
That code is located in a regular class called "MyAdapter".
There are a few ways you can do this. I can't be specific since you didn't really show any code.
You can't do what you're trying to do though. Activities can't be instantiated like that (as well as anything extending Context), and it won't do what you want.
Use a broadcast.
This will require that you have a Context object passed into your Adapter, which you can do simply by modifying the constructor and adding a global variable:
private Context context;
public MyAdapter(Context context) {
this.context = context;
}
Then you can use that Context to send a local broadcast with your own action:
Intent intent = new Intent("my_custom_action");
intent.putExtra("sound_type", 0);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
And receive that action in your Activity to call your method: See Context-registered Receivers
When you construct the Adapter, pass a Context object into it. If you're constructing from an Activity (hopefully SoundsActivity), use this:
MyAdapter adapter = new MyAdapter(this);
Use a callback.
Delcare an interface somewhere:
public interface AdapterCallback {
void onRequestPlaySound(int type);
}
Implement that interface in your Activity:
public class SoundsActivity extends Activity implements AdapterCallback {
//...
#Override
public void onRequestPlaySound(int type) {
playSound(type);
}
//...
}
Add the interface as a parameter in your Adapter's constructor:
private AdapterCallback callback;
public MyAdapter(AdapterCallback callback) {
this.callback = callback;
}
And then use callback.onRequestPlaySound(0); from wherever you need.
When you construct the Adapter, pass your SoundsActivity instance into it. This will only work if you're constructing the Adapter from SoundsActivity:
MyAdapter adapter = new MyAdapter(this);
Pass SoundsActivity directly.
This isn't the cleanest way, nor is it the recommended way, but it will work. In your Adapter:
private SoundsActivity activity;
public MyAdapter(SoundsActivity activity) {
this.activity = activity;
}
And from SoundsActivity:
MyAdapter adapter = new MyAdapter(this);
Then just call activity.playSound(0); where you need to.

Comunication through Adapter to notifyDataSetChanged()

I implemented the situation described in the image below:
The question is:
I have to update the gridView 2 when I update the GridView 1, how's the best way to do this? I could update the GridView 2 only in its Adapter by do a new Volley Request, maybe I could do this by re-set the adapter in the Fragment 2, Could I use a reference to the Fragment 2 in the Adapter GridView 1 ?
Details:
The GridView 1 is updated by a notifyDataSetChanged() on the Adapter performed after a Volley request by the Adapter itself. I can't use the onResume() method of Fragment 2 because it's not called due to this fragment it's showed at the same time of the Fragment 1.
Any Idea?
Thanks.
A listener is just an interface in JAVA. So you can not create an object of an interface ("new" operator)
1) Create an interface
public Interface OnUpdateGridView2Listener{
public void onUpdate() //Add the kind of data you want in the parameters
}
2) Create a member of the interface in the adapter of gridView1 and call its method
public GidViewAdapter1 extends Adapter{
private OnUpdateGridView2Listener myListener;
//Your code
#Override
public void notifyDataSetChanged(){
//Your code
myListener.onUpdate();
}
public void setOnUpdateGridView2Listener(OnUpdateGridView2Listener list){
this.myListener = list;
}
}
3) Implement the interface in your fragment and notify the adapter
public FragmentGridView2 extends Fragment implements OnUpdateGridView2Listener{
#Override
public void onUpdate(){
//Your code
gridView2Adapter.notifyDataSetChanged();
}
}
4) In your activity, set the listener when you create your fragmentGridView1
public YourActivity{
//Your code
FragmentGridView1 fragment = new FragmentGridView1();
fragment.setOnUpdateGridView2Listener(getApplication());
}
You could try to implement a Listener pattern like this:
FragmentTab2 {
private interface DataListener {
public Data getData();
}
private DataListener dataListener = new DataListener();
Data = dataListener.getData();
}
FragmentTab1 implements DataListener {
#Override
public Data getData() {
return Data;
}
}
Or a bit more involved should you need to notify, register, and unregister listeners try this here: Observer Design Pattern

Access variables from different methods

What I need is simple:
If oncreate I have an arraylist created with some items.
But, how can I edit that arraylist(add items,remove) from another function(method)?
Just use a object field:
public class X extends ThatAndroidAppClassWhatsNameIForgot {
private List<ItemType> list = new ArrayList<ItemType>();
public void onCreate() {
list.add(...);
}
private void otherMethod(...) {
list.remove(...);
}
}
create that array list as a private field of your class. That way it will be visible to oncreate method or any other

Categories

Resources