Is there a way to add views to a ViewPager (by adding data and calling notifyDatasetChanged() on its PagerAdapter) without changing the view currently being displayed?
I want the dataset to update in the background while the user is viewing other views. My problem now is that, when it finishes updating, it goes back to displaying the initial view. How can I prevent it from doing so?
As far as i know if you call notifyDatasetChanged() it only notifies the pager adapter that there is new data, the data has to be there before. so i think you should just not call notifyDatasetChanged() and when the user goes to the next view, the pageradapter loads the current (new) data. What about this solution?
Related
I'm wondering what does notifyDataSetChanged() actually do.
I was trying to navigate source code so I found it calling notifyChanged() method in a static member class that called AdapterDataObservable
notifyChanged() loops through data and call onChange() which is empty body.
So I can see nothing notifyDataSetChanged() did, how does my view change?
A method setAdapterInternal() is called when either setAdapter or swapAdapter are called, and it actually registers your RecyclerView as observer of changes in the adapter.
The data changes in your adapter, the adapter is the one responsible for watching your dataset, and it just let's the view know when the data changes, to adjust it's layout or bounds or whatever is needed to account for the data changes.
Is it somehow possible to force adapter to redraw only specific item?
Currently if I want to redraw the list, I call notifyDataSetChanged() which re-iterates through all the data-set and redraws all elements. What if I know exactly which element was updated and I want to redraw only that one?
notifyDataSetChanged() is not for redrawing elements, it is for notifying the adapter, that the elements have changed in some way, for example there are more elements, or their data is set from an other class etc. Of course, the ListView (or other class), to which the adapter is connected will redraw the elements, becuase the Adapter is forced to tell him, its dataset is changed.
As Yume117 commented, for redrawing you can call one View's invalidate() method (or even better postInvalidate()),
postInvalidate():
Cause an invalidate to happen on a subsequent cycle
through the event loop.
public void invalidate ()
Added in API level 1
Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().
You can call these methods on one view in the Adapter's getView() method, or only call invalidate on the ListView (or other view) itself, and it will only redraw the visible elements.
You can create singletone object with Map. And then put every View of your object to this map. And after all, you can change this object, redraw your specified View (you have to know position) and then call notifyDataSetChanged().
There is no such method out of box, which is not so bad as not whole dataset gets re-iterated and not all elements gets redrawn, but just currently visible ones. These are usually not so many.
I have a listView inside Activity inside tab layout. If I long press the item, I get the option to rename the item. Once the item is renamed, the change can't be seen until the activity is restarted.
I tried solving the problem by simply creating a new intent and re-opening activity, but since that activity is inside tablayout it doesn't work. I also tried re-opening tabLayout activity but then it automatically goes to tab 1, while I'm trying to refresh listView inside tab 2.
So then I tried solving it by creating updateListView() method:
public void updateListView(){
listAdapter.clear();
listAdapter.addAll(recordedFilesArray);
listAdapter.notifyDataSetChanged();
}
But that doesn't work either. When I'm using this method, it completely clears listView and then I have to restart the activity again to see the results.
So, anyone have any idea what I could do to see listView changes without restarting the activity? By the way, if it helps, I'm reading ListView (ArrayList) from a text file.
Try using notifyDataSetChanged() only without clearing your listAdapter
You can make a separate adapter class and implement its getView() function to manage this. Your activity will pass the array list to the adapter. The adapter's getView() will take care of displaying the contents from the list.
When the list gets modified, you need to reinitialize the adapter. So that way getView() always have the updated data to display on the screen.
For renaming the item, you can change your item object in the ArrayList,
and then call adapter.notifyDataSetChanged().
I found the problem. The ArrayList wasn't changed until the activity was restarted. I had to call arrayList.set() to change the element in the ArrayList. Now it works as it should.
My code:
recordedFilesArray.set(toDelete, input.getText().toString()); //toDelete is arg2 variable (onLongItemClickListener)
listAdapter.notifyDataSetChanged();
I am using a ListFragment with a custom adapter, which is used to inflate the views. The data is loaded via an AsyncTaskLoader once the fragment is created.
My problem is now that I want to scroll (not smooth scroll) to a certain position to show the last selected element, i.e. The fragment gets destroyed when I select an element and I want to show the same position in the list once the fragment is displayed again.
So creating the view and everything works fine, but I do not know where to add the getListView().setSelection(x) line to scroll to a certain position. I tried to invoke it after clearing and adding the elements to the adapter in Loader<?>.onLoadFinished() function, but that does not work, I get the following exceptoins:
java.lang.IllegalStateException: Content view not yet created
at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
at android.support.v4.app.ListFragment.getListView(ListFragment.java:222)
at fs.pokemon.effect.PokemonFragment.updateData(PokemonFragment.java:239)
at fs.pokemon.effect.PokemonFragment$2.onLoadFinished(PokemonFragment.java:129)
...
My question is: Is there a function/callback so I get notified, when the ListView has finished updating its content? Or how else can I scroll the View to a position after the content has loaded?
Thanks to pskink comment I tried it again and noticed that the exception does not occur in setSelection() but rather in getListView() - I though my loader would reload data after the view was created, but instead it used the cached results, so onLoadFinished() was actually called, before the initialization of the fragments view was finished, thus causing an exception.
The correct way to do it is to determine the position in onLoadFinished() and then override the fragments onViewCreated() and execute getListView().setSelection(curPosition) there.
Probably also the case that the loader cleared its cache and the onLoadFinished() will be called after the onViewCreated() method has to be considered, but so far it works fine.
Set the transcript mode and stackfromBottom for the listview while your listfragment activity is created. Now every time the listview is updated it will be scrolled to bottom to the latest item.
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
getListView().setStackFromBottom(true);
}
If I have a fragment where I dynamically set a view with onCreateView(), how would I go about calling it again?
I want to implement some kind of "refresh" where the view changes based on the JSON response. I tried making a new function that does midnightSV.removeAllViews(), but how can I call onCreateView() again?
You can't without detaching and re-attaching the fragment.
If you just want to update the data in the view, you can find those views and refresh them from the existing fragment.
If you really want multiple sets of unique layouts, you can look into using a ViewFlipper for your fragment layout and then call setDisplayedChild() to switch to a specific view.