Adapter not working - android

In my OncreateView() set the adapter which is working when i am first loading the page. When i go to another page and make changes then come back to this fragment it is not working adapter.notifyDatasetchanged().
#Override
public void onStart() {
super.onStart();
groupItem.clear();
childItem.clear();
List<String> child_Category;child_Category=new ArrayList<String>();
groupItem = obj_Listdatabase.fetchcategory();
childItem.clear();
ListIterator<String> iterator = groupItem
.listIterator();
while (iterator.hasNext()) {
String categoryname = iterator.next();
child_Category = new ArrayList<String>();
child_Category = obj_Listdatabase
.fetchchildlist(categoryname);
childItem.add(child_Category);
}
adapter.notifyDataSetChanged();
}

Hai I got output for this one:
groupItem.addAll(obj_Listdatabase.fetchcategory());
Instead of This
//groupItem = obj_Listdatabase.fetchcategory();
Because i change the reference in assignment statement(=) for that adapter.So i use addAll() method to store the values only instead of reference.

You should reaaaally indent your code more cleanly, never use several ";" on the same line for example.
And you can definitely use BaseExpandableListAdapter the issu is somewhere else..
You should also notice that onCreate view is more suitable for "creating view" so all the adapter stuff should be somewhere else like onViewCreated, or onActivityCreated as you need (it's just some advices)
I assume your adapter is in a Fragment since you use GetActivity() and in the constructor of your adapter you pass a reference to the activity (context), the group list and the child list.. ok
we ll assume that you are using the fragment onStart. From the official doc :
Called when the Fragment is visible to the user. This is generally tied to Activity.onStart of the containing Activity's lifecycle.
So normally this method is called after onViewCreate, onViewCreated .. etc at least the first time you code is running. So this is ok
Did you try using adapter.notifyDataSetInvalidate() and then do adapter.notidyDataSetChanged ?
One last thing, since you actually pass the data to your adapter by the constructor, when you update your lists how can the adapter be aware of the changes ? Are your lists global (static) ?
If not, before doing adapter.notifyDataSetChanged() you should pass the lists (group and child) to the adapter with some setter..
good luck

Related

Android RecyclerView infinity scrolling: how to add more items to dataset

I have implemented my RecyclerView and even added an onscrolllistener to support infinity scrolling and now I'm stuck with a, hopefully, easy problem: How can I add the newly loaded data to the existing dataset?
My current approach: I create a new array with the length of the existing dataset + the length of the newly loaded data. I System.arraycopy my existing dataset and add the new content with a for-loop.
This works but the list is always reset (scrolls back to the top) and I assume my way to add additional content is overly complicated/wrong, though the tutorials I have looked at seem to pass over this "detail".
Update: I'm currently calling "scrollToPosition" on the UI-Thead after the data has been loaded, but I doubt this is the correct way of doing this or am I wrong?
You shouldn't be adding stuff to your dataset, you will sooner or later run out of memory. What you can do is return a big number (I used Short.MAX_VALUE) item in getItemCount inside your adapter and in the method that requests a view for postion you should do position % list.size();
It is not a truly endless RecyclerView this way, but good enough. I will paste some code tomorrow, I don't have it here now :/
I think you have to add items inside your adapter. Let`s say
class Adapter extends Recycler.Adapter<Recycler.ViewHolder>{
List<YourCustomObject> list;
public Adapter(){
list = new ArrayList<>();
}
public void addItem(YourCustomObject item){
list.add(item);
notifyItemDateSetChanged(); //This method for adapter to notice that list size have been changed
}
// Here your views
}
There is implementation of Your fragment or Activity where you retrieve data from internet.Let` say
class MainActivity extends AppCompactActivity{
Adapter adapter = new Adapter();
List<YourCustomObjects> objects;
public void onCreateView(){
//////// Something yours
}
public void onLoadMore(){
///// Your operation to retrieve data and init it to your list objects
for(YourCustomObject object : objects){
adapter.addItem(object);
}
}
}

Update custom listview item attribute

I am using listview in my app.I am adding items to list with this line:
conversationsAdapter.add(user);
and this initializes list
conversationsAdapter=new ArrayAdapter<JsonObject>(this,0) {
#Override
public View getView(int c_position,View c_convertView,ViewGroup c_parent) {
if (c_convertView == null) {
c_convertView=getLayoutInflater().inflate(R.layout.random_bars,null);
}
JsonObject user=getItem(c_position);
String name=user.get("name").getAsString();
String image_url="http://domain.com/photos/profile/thumb/"+user.get("photo").getAsString();
TextView nameView=(TextView)c_convertView.findViewById(R.id.tweet);
nameView.setText(name);
ImageView imageView=(ImageView)c_convertView.findViewById(R.id.image);
Ion.with(imageView)
.placeholder(R.drawable.twitter)
.load(image_url);
return c_convertView;
}
};
ListView conversationsListView = (ListView)findViewById(R.id.conversationList);
conversationsListView.setAdapter(conversationsAdapter);
conversationsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
startChat(conversationsAdapter.getItem(position));
}
});
My list view is looking like this:
I want to update an item in the list.How can I do this ?
Example:We can write a method like: changeName when this method calls,method sets name "Tolgay Toklar" to "Tolgay Toklar Test" so I want to update custom listview item attributes.
I totally disagree with tyczj. You never want to externally modify an ArrayAdapter's list and yes it's possible to update just an individual item. Lets start with updating an individual item.
You can just invoke getItem() and directly modify the object and call notifyDataSetChanged(). Example:
JSONObject object = conversationAdapter.getItem(position);
object.put("name", data);
conversationAdapter.notifyDataSetChanged();
Why does this work? Because the adapter will feed you the same object reference used internally, allowing you to modify it and update the adapter. No problem. Of course, I'd recommend instead building your own custom adapter to perform this directly on the adapter's internal list. As an alternative, I highly recommend using the ArrayBaseAdapter instead. It already provides that ability for you while fixing some other major bugs with Android's ArrayAdapter.
So why is tyczj wrong about modifying the external list? Simple. There's no guarantee that your external list is the same as the adapters. Once you perform a filter on the ArrayAdapter, your external list and the adapters are no longer the same. You can get into a dangerous scenario where (for example) index 5 no longer represents position 5 in the adapter because you later added an item to the adapter. I suggest reading Problems with ArrayAdapter's Constructors for a little more insight.
Update: How External List Fails
Lets say you create a List of objects to pass into an ArrayAdapter. Eg:
List<Data> mList = new ArrayList<Data>();
//...Load list with data
ArrayAdapter<Data> adapter = new ArrayAdapter<Data>(context, resource, mList);
mListView.setAdapter(adapter);
So far so good. You have your external list, you have an adapter instantiated with it and assigned to listview. Now lets say at some later point, the adapter is filtered and cleared.
adapter.filter("test");
//...later cleared
adapter.filter("");
Now at this point mList is NOT the same as the adapter. So if the adapter is modified:
adapter.add(newDataObject);
You'll find that mList does not contain that new data object. Hence why external lists like this can be dangerous as the filter creates a NEW ArrayList instance. It won't continue to use your mList referenced one. You could even try adding items to mList at this point and it won't be reflected in the adapter.
If you change the data in your list you need to call notifyDatasetCanged on the adapter to notify the list that the underlying data has changed needs to be updated and.
Example
List<MyData> data = new ArrayList<MyData>();
private void changeUserName(String name){
//find the one you need to change from the list here
.
.
.
data.set(myUpdatedData);
notifyDatasetChanged()
}

ViewPager updates listView in fragment B from a fragment A

I have a ViewPager with two Fragments. On the first one, there are buttons (it is a menu) and they represent different categories. On the second one, it is a listView which display data.
I am looking for a way to change the data to display on the listView when the user click on one of the menu items.
For example : the user click on the menu item 1 (fragment 1), the listView on the fragment 2 have to be updated with the corresponding data.
I read the documentations from Google Android developer about fragments but I couldn't work it out, I didn't find a solution to my problem.
Maybe I'm missing something ?
EDIT : I tried to clear my ListView by clearing the list of data (ArrayList> listItems) with listItems.clear(). I didn't find how to do adapter.clear(), it seems that this method doesn't exist in the class Adapter.
So to summarize : I created an update method in my fragment which contains the ListView (Fragment2). I called it through a callback method in the main activity, that part seems to work (I checked it with debug mode).
In the update method of my Fragment 2, I clear data with listItems.clear() and then the OnActivityCreated() of the fragment is executed. In it, there is the call of my thread which download data and then it create the ListView in OnPostExecute.
Here is a sample of my code (fragment2) :
// After data are ready
lvListe = (ListView) getView().findViewById(R.id.lvListe);
lvListe.setSelected(true);
lvListe.setScrollingCacheEnabled(false);
adapter = new LazyAdapter(getActivity(),
getActivity().getBaseContext(), listItems,
R.layout.affichageitem, new String[] { "image", "title",
"subtitle" }, new int[] { R.id.img_title,
R.id.titre_main, R.id.soustitre_main });
lvListe.setAdapter(adapter);
lvListe.setClickable(true);
lvListe.setOnItemClickListener(onItemClickListener);
// Update method :
public void update(String requete, String type)
{
this.type = type;
this.requete = requete;
listItems.clear();
}
The way that I would probably do it is to create a callback method in the Activity hosting the ViewPager and also a method in the second Fragment to update the data.
Then you would call it like:
class Fragment1...
{
...
callBackUpdate(data);
}
class Activity...
{
...
public void callBackUpdate(String data)
{
Fragment2.update(data);
}
}
class Fragment2...
{
...
public void update(String data)
{
//do whatever
}
}
The developers page shows how to create a callback method to the Activity.
edit: Actually that's how the Developer's page says to do it. They create the interface OnArticleSelectedListener for the callback.
edit: I'm assuming you are using this library for the LazyLoader: https://github.com/thest1/LazyList
If so, then you can just add the method to clear the data yourself. To do so, add a method like this in ListAdapter:
public void clear()
{
data = new String[](); //depends on what data is, if it's a List then just call data.clear() for example
imageLoader=new ImageLoader(activity.getApplicationContext()); //clear the images
notifyDataSetChanged(); //notify the adapter that the data has changed
}
This might not exactly fit how you currently have it, but you should get the idea.
Try using something known as a FragmentTransaction manager at http://developer.android.com/reference/android/app/FragmentTransaction.html
and also the FragmentManager http://developer.android.com/reference/android/app/FragmentManager.html
Check out some of the questions on stackoverflow related to FragmentManager and FragmentTransaction to figure this out. All you need to do is replace the fragment with a new one which is inflated by a particular xml

Strange behavior with ArrayAdapters in Android

I've been playing around with ArrayAdapters and I've reached a point where I'm getting different results from two almost identical ArrayLists + ArrayAdapter combinations.
The first one:
An ArrayList of 'Restaurant' objects, an ArrayAdapter that uses this ArrayList and a ListView that binds this ArrayAdapter.
private ArrayList<Restaurant> model = new ArrayList<Restaurant>();
private ArrayAdapter<Restaurant> restaurantAdapter = null;
...
public void onCreate(Bundle savedInstanceState){
...
restaurantAdapter = ArrayAdapter<Restaurant>(this, android.R.layout.simple_list_item_1, model);
...
listView.setAdapter(restaurantAdapter);
...
}
The second one:
An ArrayList of String objects, an ArrayAdapter that uses this ArrayList and a AutoCompleteTextView that binds this ArrayAdatper.
private ArrayList<String> prevAddressList = new ArrayList<String>();
private ArrayAdapter<String> addListAdapter = null;
...
public void onCreate(Bundle savedInstanceState){
...
addListAdapter = ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, prevAdddressList);
...
autoCompleteField.setAdapter(addListAdapter);
...
}
I have a save button, on click, I'm creating a restaurant object with a name and an address and adding it to the first adapter, additionally, I want to create a list of previously used address so they are "auto completed" next time they are typing it, so I'm taking the text, and adding it to the second adapter.
...onSave = new View.OnClickListener(){
...
restaurantAdapter.add(r); //r is a Restaurant object.
addListAdapter.add(autoCompleteField.getText().toString());
...
}
Now, everything is working properly. I get the Restaurants displayed in a ListView. The AutoComplete is working as expected.... but I noticed something when I was checking the values while debugging:
The actual ArrayLists, model (Restaurant) is getting updated after adding an object to the adapter , but prevAddressList (String) is not.
Unless, I set the AutoCompleteTextField empty.... then, the prevAddressList gets updated after adding something to the second adapter.
Already tried using notifyDataSetChanged(), but it makes no difference (and it is set to true on every adapter by default anyway).
Other behavior that differs between the two adapters is that in the first one (Restaurant), values are going to the mObjects field, while in the second one (String) they are going to mOriginalValues instead.
I'm completely stomped. The only difference between those two adapters is that one is type "Restaurant" and the other is type "String".
Any ideas? Maybe I'm missing something very obvious? Let me know if you need the full code.
thanks
Instead of adding it to the adapter, try adding the object to your list and then calling notifyDataSetChanged on your adapter. The adapter should pick up your changes and your list of course will have the object you just added.
For anyone coming here from google:
Unable to modify ArrayAdapter in ListView: UnsupportedOperationException
This might explain the behavior, although I have to test it myself.

Call a method from an activity from an adapter

I am working with an adapter which has several buttons on each item of the ListView. I have, for example two buttons. One for save and another for delete.
When I click on them, I want the adapter to refresh. I have a method on my activity that does that: Update the adapter. I made it since I couldn't make the Notify methods of the adapter work.
I am sending the Activity to the adapter as a parameter and then call the update method from the adapter since I am setting the OnClick methods of each button in the adapter.
The problem is that it doesnt seem to work always. I am guessing it has to do something about the cycle of the activity and Android cleaning memory however I can't seem to understand where is the problem.
I am aware this is some ugly way of doing it, so what should be the best way of doing this?
Summary: I need to refresh the adapter from the adapter itself when I delete an item of the ListView or update it (BaseAdapter)
Edit:
I am adding some code. This is my constructor of my adapter:
public SpendingPlanAdapter(Context context, SpendingPlan sp, int month, int year, money.activities.SpendingPlan act)
Inside the adapter I have an OnCLickListener attached to a button. I am calling the update method like this (Result is the result of a database insert):
if (result){
Toast.makeText(context, context.getResources().getString(R.string.succesfully_deleted), Toast.LENGTH_LONG).show();
act.updateAdapter();
} else {
Toast.makeText(context, context.getResources().getString(R.string.oops), Toast.LENGTH_LONG).show();}
And this is my UpdateAdapter method:
public void updateAdapter(){
SpendingPlanAdapter adapter = new SpendingPlanAdapter(getApplicationContext(), currentSp, currentMonth, currentYear, this);
limitList.setAdapter(adapter);
}
You can call updateAdapter() like this
(SpendingPlan (context)).updateAdapter();

Categories

Resources