How to access variable in a Activity, from childView? - android

I have a view as following hierarchy.
The main Activity has
ArraylistArrayListArraylist()
I want to access and change the data of the Arraylist from the button of the Card view. I'm using Custom ArrayAdapter. So is there are any way to do this?

You just need to pass your list data from activity to your custom adapter by calling adapter's constructor. See below how you can pass list data and that from adapter.
public TestAdapter extends ArrayAdapter<String>{
private Context mContext;
private List<String> list = new ArrayList<>();
public MovieAdapter(#NonNull Context context, #LayoutRes ArrayList<String> list) {
super(context, 0 , list);
this.mContext = context;
this.list = list;
}
.............//use "list" in your adapter
}
In activity you have below list.
Arraylist a = new Arraylist();
a.add("test");
a.add("test1");
a.add("test2");
a.add("test3");
TestAdapter testadapter=new TestAdapter(this,a);
Now you have that list in adapter and you can use list in your adapter.

Related

How to use Picasso in an Adapter without using context in Fragment

When I try to use context in my fragment I get the error:
constructor Adapter in class Adapter cannot be applied to given types;
required:Context,List<ListItem>,OnItemClickListener
I have declared my context in my adapter as follows:
private Context mContext;
then i initialized the context:
public MyAdapter(Context context,List<ListItem> listItems, OnItemClickListener callback) {
this.listItems = listItems;
this.callback = callback;
this.mContext = context;
}
And used mContext to get my imageurl in the onBindViewHolder using picasso
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ListItem listItem = listItems.get(position);
Picasso.with(mContext).load(listItem.getImageurl()).into(holder.imageUrl;
}
But now I can't seem to get around using this context in my Fragment.
This is what I've tried: In my Fragment:
//an error occurs
adapter = new MyAdapter(this,listItems);
so I tried this:
//still get an error
adapter = new MyAdapter(getContext(),this);
I also tried getActivity but still get an error
adapter = new MyAdapter(getActivity());
where am I going wrong?
All I am really trying to do is display the image in my listfragment but I don't know how to use Picasso with using context, and MyAdapter does not require context to function properly. I've been using it without declaring context and the data displays properly. Onclick is also working and displaying strings from firebase, but now I need to display images from Firebase using Picasso into my listfragment. Everything else works fine except this line of code in my Fragment:
adapter = new MyAdapter(getActivity());
You try Get context from any View object in Holder.
Example:
mContext = holder.imageView.getContext()
In your adapter initialization you pass 2 parameters, but your constructor requires 3 parameters.
so try to initialize using 3 params:
adapter=new MyAdapter(getContext(), listItems, this);
getContext()= context of fragment.
lisItems= your list.
this=is your click interface listener (make sure you implemented the listener in your fragment).
Try this, I think you forgot last argument
OnItemClickListener listener = OnItemClickListener {
void onItemClick(int position) {
//some code
}
}
adapter = new MyAdapter(this, listItems, listener);
Fragments are inflated inside an Activity.
In Fragment, you either use the context of the Activity or the context of the whole application.
Plus you have missed passing one more parameter in the Adapter, ie your click listener.
Define the adapter like this -
OnItemClickListener mOnItemClickListener = OnItemClickListener {
void onItemClick(int position) {
}
}
adapter = new MyAdapter(getActivity(), listItems, mOnItemClickListener);
or
adapter = new MyAdapter(getActivity().getApplicationContext(), listItems, mOnItemClickListener);

Error in initialization of custom array adapter

I am trying to make a custom listview. The list is declared as below
List<DocRow> doctors = new ArrayList<>();
This list is then being populated.
My custom array adapter is in a separate class with its constructor declared as below.
public class DocAdapter extends ArrayAdapter<DocRow>{
Context context;
int resource;
ArrayList<DocRow> doctors;
private LayoutInflater inflater;
public DocAdapter(#NonNull Context context, #LayoutRes int resource, ArrayList<DocRow> doctors) {
super(context, resource, doctors);
this.context = context;
this.resource = resource;
this.doctors = doctors;
inflater = LayoutInflater.from(context);
}
Now in my main activity, I am trying to create a new custom array adapter by passing off my list (which is a valid parameter), it isn't accepted. The code for creation and setting of adapter for linking the listview with the list is below.
DocAdapter adapter = new DocAdapter(getApplicationContext(), R.layout.doc_row, doctors);
docList.setAdapter(adapter);
Can anyone explain what is the issue? The link for error screenshot is above. I tried searching for this specific issue, but haven't been able to find a solution that works.
Change your constructor argument to List instead of ArrayList as you are passing list in it.
List<DocRow> doctors;
public DocAdapter(#NonNull Context context, #LayoutRes int resource, List<DocRow> doctors) {
super(context, resource, doctors);
this.context = context;
this.resource = resource;
this.doctors = doctors;
inflater = LayoutInflater.from(context);
}
As pointed by #Tim, here is a little detail about why this is needed.
When an instance is initialized, it may be initialized with one of its child classes but the object remains an instance of Super class only(Due to runtime polymorphism) and therefore the methods that consume this instance either expect super class or the instance should be casted to superclass before passing it on.
The easiest way to identify is to always look at the type on the left-hand side instead.
List a=new ArrayList();
In above example, the instance is actually an arraylist but it is of Type List.
A parent class's reference can store subclass's object, but the reverse is not true.
Here, in the constructor of your adapter, you have ArrayList<DocRow> as your parameter type, but your doctors list is of type List<DocRow>. You, you're passing a List<> object to an ArrayList<> reference.
To solve it, either change your doctors variable type to ArrayList<>, or your constructor parameter type to List<>

Recycler view adapter not reflecting changes

So I have a recycler view adapter set up in my MainActivity. That adapter is hooked up to an arraylist of a custom object I made called group.
public static RecyclerView.Adapter groupsListAdapter;
public ArrayList<Group> myGroups;
//inside onCreate of Main Activity
groupsListAdapter = new MyAdapter(myGroups);
In a different Activity, I am updating the contents of this arraylist, first by passing it through the intent.
Intent groupCreationIntent = new Intent(MainActivity.this, NewGroupActivity.class);
groupCreationIntent.putExtra("groupsList",myGroups);
startActivity(groupCreationIntent);
And then updating it in the other activity.
private ArrayList<Group> groups;
//in oncreate method of other activity
groups = (ArrayList<Group>) getIntent().getSerializableExtra("groupsList");
When going back to the previous activity (the second activity is used for entering some information and syncing it with my database) I run this code.
groups.add(myGroup);
MainActivity.groupsListAdapter.notifyDataSetChanged();
finish();
The problem is that the list adapter is not reflecting the changes, nothing is appearing in my list once i return to the main activity. What am I doing wrong?
class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Group> items;
public MyAdapter(List<Group> items) {
this.items = items;
}
// .. your implementation
// add and call this
public void add(Group item) {
this.items.add(item);
notifyItemInserted(items.size() - 1);
}
}
it's not related with your question, you should not use static field for Activity-to-Activity communication.

getting context of fragment in baseadapter

this has became some thing complicated for me since im not so much familiar with fragments but it might also be simple for some of you guys, here i had this part of code referring to an activity, when i changed the activity to fragment it says can not cast from context to ListViewActivity, can you please help me solve this:
#Override
public Filter getFilter() {
return ((ListViewActivity)mContext).new ListFilter();
}
obviously mContext is a context reference.i understand that inside the fragment should get context with getActivity(), but from outside ?thanks a lot.
I would construct a custom adapter similar like this:
public class CustomBaseAdapter extends BaseAdapter {
Context context;
List<RowItem> rowItems;
public CustomBaseAdapter(Fragment fragment, List<RowItem> items) {
this.context = fragment.getActivity();
this.rowItems = items;
}
}
And in your fragment, call the adapter like this:
CustomBaseAdapter adapter = new CustomBaseAdapter(this, items);
Now you can cast the context in your adapter to ListViewActivity, assuming the fragment is part of ListViewActivity.
Hope this helps!

Android ListView adapter data, mantaining consistency

When you create a custom adapter extending ArrayAdapter<T>, it has usually the form:
public class ListAdapter extends ArrayAdapter<Item> {
private List<Item> mData;
public ListAdapter(Context context, int resource, List<Item> data) {
super(context, resource, data);
mData = data;
}
}
The data is initially saved in a private member mData, but also the ArrayAdapter saves the data in its own member mObjects. I am pretty sure those are not actual copies, but references to the same list.
Now, and this is my question, if during the ListView processing, for some reason, you have to replace your own list with a fresh new List, I think you should also do:
mData = new List<Item>();
super.clear();
super.addAll(mData);
otherwise there will be no consistency in ListView, and methods like getFilter().filter() will not work.
Am I correct?
I think, when you say mData = data; it only copies pointer of the data array, because when you execute that;
ListAdapter adapter = new ListAdapter(context, resource, data);
data.clear();
adapter.notifyDataSetChanged();
it changes list. So it keeps pointer of your source array,
Second, I think (not sure) you cannot use filter function of adapter, at least I couldn't use and write my own filter function. I filter elements from sqlite(I take my elements from database). and use notifyDataSetChanged function of adapter.
You are right. Your ListAdapter doesn't make a deep copy of the provided list of Items. This means that changing an Item instance 'outside' the ListAdapter will put the ListAdapter in an invalid state.
However, you can 'fix' this by calling notifyDataSetChanged on the ListAdapter.
List<Item> itemList = ....
....
....
ListAdapter adapter = new ListAdapter(this, R.layout.somelayout, itemList);
....
Now, if you change an item 'outside' the ListAdapter, you can still make your ListAdapter be in sync with the change:
itemList.get(idx).changeSomethingInItem("Hello"); // Changes the Item at index 'idx'.
adapter.notifyDataSetChanged(); // Notify adapter about this change.
you really needn't pretty sure whether it actual copies or not ,just extend BaseAdapter

Categories

Resources