Extending BaseAdapter, when does the view become null? - android

public class CustomAdapter extends BaseAdapter
I found a code that extends BaseAdapter
public View getView(int index, View view, final ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.single_list_item, parent, false);
}
}
TextView textView = (TextView) view.findViewById(R.id.tv_string_data);
textView.setText(dataModel.getName());
my question is when view == null ?
why we need the code if (view == null) {}
thanks

A ListView typically contain more data then the number of displayed rows. If the user scrolls the list then rows and their associated Views will be scrolled out of the visible area. The Java objects which represents the rows can be reused for newly visible rows.
If Android determines that a View which represents a row is not visible anymore it allows the getView() method to reuse it via the convertView parameter.
A performance optimized adapter assigns the new data to the convertView. This avoids inflating an XML file and creating new Java objects.
In case no View is available for reuse, Android will pass null to the convertView parameter. Therefore the adapter implementation need to check for this.

For the first item in the listView the View will be null. It needs to be inflated for the first item.
Please be free to ask any further doubts.

Android re-cycles View objects to minimize object creation and memory usage. The View that is passed to you will either be null, in which case you are expected to create it, or the view will be non-null which means it has been re-cycled. Re-cycled views are ones that you may have created earlier, but can now be used for a different purpose.
A good example of this is a listview. A list may have many elements, say 100. The screen however may only display 10 items of the list. Thus when you scroll the screen, views that were for items no longer on the screen may be passed to you for re-use. This is re-cycling.

For list view we have to provide view for each and every item, and also we have to fill contents also. In most cases the same view will be repeated in every item with different content. So at the first time in getView method we will check, if view is null then we should inflate a view and fill the contents and return. At second time the view will not be null. So you can reuse or provide different view.

Related

why ListView always reload on

i use ListView to display a list of 30 products.
protected class ListProductAdapter extends ArrayAdapter<Product>
implements View.OnClickListener {
...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
I noticed that when I display the activity, it first calls getView 6 times, then if I scroll down, getView will be called to display other products, but if then I scroll up, getView is called again on product for which getView had already been called. Isn't it possible to get it in memory to not have to recalculate everything I scroll down and up ?
The ListView recycles its Views precisely so you do not have to have a View for every item in memory all the time, but it passes an old View as convertView so it can be reused and doesn't have to be re-inflated every time. See here.
That's how ListView works. It manages a number of views and calls getView(int, View, ViewGroup) whenever it needs one view to be set up. It doesn't hold to many views though. You might be able to hold all in memory, but that's not its intent.
If convertView is null the list needs you to create the views (your first 6 calls to getView). When you start scrolling, the list will provide you with an (already initialized) convertView which you only need to refill with the data you want to display.
See the documentation of getView for an elaborate explanation.

Get child view inside a Listview Adapter

Inside my getView method I want to get a specific child view. I know that my adapter holds several items, by doing calling getCount:
getCount();
According to the JavaDoc:
public abstract int getCount ()
Added in API level 1
How many items are in the data set represented by this Adapter.
Now in my getView method:
public View getView(final int position, View convertView, ViewGroup parent) {
View lastAddedItem = parent.getChildAt(getCount()-1);
if(lastAddedItem == null) {
Log.w("ListAdapter", "View is null");
}
}
This message always appears in the LogCat, which means that the View I try to grab is Null.
I've also tried this:
View lastAddedItem = parent.getChildAt(parent.getChildCount()-1);
So how can I grab a specific view from my ViewGroup object?
I know that my adapter holds several items, by doing calling
getCount:
Yes it does, but the getCount()(returning the items in the Adapter) method of an adapter has nothing to do with getting the children of a ListView with getChildAt()(where you should use getChildCount() as this will return the Views present in the ViewGroup).
lastAddedItem = parent.getChildAt(parent.getChildCount()-1);
This should return a non-null view, the last view returned by the getView() method.
I just want to animate a specific View in my ViewGroup
If you are going to animate a list row(or part of that row) when it becomes visible than register a scroll listener for the ListView and start the animation from there when the target view is appearing on the screen.
I don't how are you implemented the rest of the adapter, but if you are doing it in the right way, and I am right, the parent only contains the Views being displayed on the device's screen, and each time you pull down or pull up the list, it modifies the content of those views, that is why you get Null.
What you want to achieve (animate a view), should be done in runtime, checking if the view currently being displayed in the screen should be animated or not.
Hope it helps.

Android:Problems with listview when I scroll the list and is disordered

I have an adapter for a ListView which dynamically gets relative layouts to display images and text loaded into the Adapter.
The problem is that when I scroll in its entirety, the Listview is ordered incorrectly. I tried using ViewHolder but that has not solved the problem.
I wonder if there is any other way to do it. Or integer Listview load without execute code that once adapter has already been loaded list.
The main problem is that the images of the other RelativeLayout layouts appear in the wrong list.
Now The problem I have now is that when you scroll through the list slowly shows fine, but if the scroll in the list is fast elements are dislodged. As if not process fast enough position parameter. public View getView(int position, View convertView, ViewGroup parent)
Check your ListAdapter's getView(); make sure that if convertView is null that you are creating it. In both cases you want to update convertView with new data, otherwise you'll have these issues (as Android will recycle those views but not update them).

Do I need to config ConvertView properties if it is not null?

In a custom adapter, how to know weither I need to reconfig the convertView or not?
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = (ImageView) mInflater.inflate(R.layout.avatar, parent, false);
// Should this 2 lines of code be here ?
User user = mUserList.getUserAt(position);
user.setAvatar(imageView);
} else {
imageView = (ImageView) convertView;
}
// or here ?
User user = mUserList.getUserAt(position);
user.setAvatar(imageView);
return imageView;
}
I would think that if it is recycled, I would not need to reset the user's avatar but I often see the configuration happening outside of the if block. Why is that?
I always configure the view outside of if block. This convertView that you get in the getView method might (and most probably will) be set up for another user by some previous call to getView because of ListView's policy to reuse item views when they go offscreen. If you do not set up a proper avatar you will have wrong one for this item. Of course you won't need to reset properties that are independent of the concrete position like background.
For example CursorAdapter separates getView into two parts: newView, that performs inflate and (mostly) position-independent setup and bindView that assigns actual position-dependent data.
It may also happen that you will get exactly the same view that you used for this position earlier. Of course you can avoid resetting a view in this case, but you need to check if data in this view are valid. Setting and then checking View's tag comes to my mind as a most obvious solution.
It is not truly recycled, it just means that you need to fill a "recycled" view with new data according to the its new position. If you don't do it this row will be filled with old data that shouln't be visible on the screen anymore since you scrolled away its position.
So in short you have to reconfigure view with fresh data each time getView() called (outside of if block in your code).
Your issue is only with the understanding of listview.
So here I'll make you clear how it works??
Let's say listview has to contain 20 items but your current screen can accommodate(show on screen) only 8 items(list items, in your case imageview).
When the listview tried to get items for 1----8th it will return you convertView as null because no recycling of objects happened yet.
but, when you try to scroll, in our case(scroll up!).
the 1st element of the list will be recycled when go out of screen, and will be supplied as convertView for 9th item.
In this way listview has to manage only 8th(in our case) to show any number of items.
The opposite will happen if we will scroll down wards.
So, on the basis of convert view (null or not) you have to design your logic either to create and fill or to fill.
Hope this will help you.

what's exactly happening in getView

I see this a lot in Adapter extensions override of getView:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.whatever, null);
}
I get semantically what's happening - "if convertView is null then inflate it", but I don't really understand why - what circumstance would convertView be null, and in what circumstance would it already be a View?
Also (and I know "1 question per post"), but as it relates to the above - what's exactly happens during the inflate method? I know what it does generally ("inflates" a view resource to be parsed and populated), but don't fully grok it...
TYIA
AFAIK, this is how getView works.
Suppose you have a list with 50 items and you can only see 5 items at a time. The getView will be called 5 times initially and the convertView will be null for each row and a new row should be inflated.
As you scroll through the list the getView will be called again as the next rows get visible on the screen. Now since 5 rows are already rendered for the list, these rows will be recycled by updating existing rows with new values to show new rows. At this case the convertView will not be null.
Say your list adapter has 1000 objects. Each object is represented by a view. On the phone screen there's place only for maybe some 10 such views. You scroll the list wanting to see more items. Some items go out of sight because you're scrolling. It makes no sense for the Framework to create more views as they will be exactly the same as those which have just gone out of sight. Framework thus can reuse some views it created before and so it offers to you such a possibility by offering you a non-null convertView.
During the inflate method a View object gets created out of some XML resource. The XML resource has a description of a View sufficient for that View to be created and so the inflate method does that creation. So no view - you create a new one by inflating, there is a view already - you can reuse it (you don't have to but you should)
for full information i recommend you to watch this video
it will tell you alot of information include what is happening in getView()

Categories

Resources