How does the getView() method work when creating your own custom adapter?
1: The LayoutInflater
takes your layout XML-files and creates different View-objects from its contents.
2: The adapters are built to reuse Views, when a View is scrolled so that is no longer visible, it can be used for one of the new Views appearing. This reused View is the convertView
. If this is null it means that there is no recycled View and we have to create a new one, otherwise we should use it to avoid creating a new.
3: The parent
is provided so you can inflate your view into that for proper layout parameters.
All these together can be used to effectively create the view that will appear in your list (or other view that takes an adapter):
public View getView(int position, @Nullable View convertView, ViewGroup parent){
if (convertView == null) {
//We must create a View:
convertView = inflater.inflate(R.layout.my_list_item, parent, false);
}
//Here we can do changes to the convertView, such as set a text on a TextView
//or an image on an ImageView.
return convertView;
}
Notice the use of the LayoutInflater
, that parent
can be used as an argument for it, and how convertView
is reused.
How does getView() work in a custom adapter?
How does getView() work in a custom adapter?
getView() method is called as many times as is number of rows e.q. each row has own View.
Now, this 'reuse' is confusing me.
It's called View recycling. In other words, if row is not visible, its not null (if was created and visible at least once) but if you won't create mechanism that will hold child views of row, recycling wont work and in your case your findViewById() will be called for each row (in the case of for example 1000 rows, its not very efficient).
For this purpose is used Holder design-pattern. It's simple arbitrary object that holds references of child views of each row.
You can implement it like:
public class RowHolder {
private View row;
// childs widgets in row
private TextView name;
public RowHolder(View row) {
this.row = row; // row in ListView (in your case)
}
public TextView getName() {
if (name == null) {
name = (TextView) row.findViewById(<id>);
}
return name;
}
...
}
And a usage:
LayoutInflater inflater;
RowHolder holder = null;
// row created first time
if (convertView == null) {
convertView = inflater.inflate(<rowXMLLayout>, null, false);
holder = new RowHolder(convertView); // adding row to arbitrary obj
convertView.setTag(holder) // adding this obj to row at position
}
else {
// recycling started
holder = (RowHolder) convertView.getTag();
}
// updating rows
holder.getName().setText(<value?>);
...
How does ArrayAdapter getView() method works?
getView()
is the main part of your adapter. It returns View
that will be displayed as your list/grid/gallary/any view that use adapter item. It triggers when you scroll the view(list for example).
So the first thing you should do its to create your custom adapter. You may extend it from BaseAdapter
. Then you need to create some data to display (or pass it to adapter from out side - its better solution).
After that override getView()
method and make sure to return your custom View there. In your case it should be a Layout
with ImageView
and TextView
(and dont forget to fill them).
You can learn more from :
- http://www.youtube.com/watch?v=N6YdwzAvwOA
- http://www.edureka.in/blog/what-are-adapters-in-android/
- http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
My getView method in my custom array adapter is not working
if(convertView!=null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent);
}
should be
if(convertView==null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent);
}
you have to inflate when the convertview is null. not when its not null. And then return this from your getView() method
Also i can not see getCount() method. It is also very important to tell the adapter about how many items to inflate
Custom adapter getview is not called
It's because getCount() returns zero.
The number you return in getCount() is the times the getView() will be called.
In getCount() you should always return the size of the list.
Therefore
@Override
public int getCount() {
return list.size();
}
@Override
public ModuleItem getItem(int position) {
return list.get(position);
}
Also, maybe the layout's ListView id is not android.R.id.list?
Make sure you have in xml
<ListView
android:id="@android:id/list"
...
Also, don't ever pass any data to a fragment in constructor.
WRONG:
public ModuleItemListFragment(List<ModuleItem> list,Module mod) {
super();
this.list=list;
this.mod=mod;
}
RIGHT:
private static final String EXTRA_LIST = "ModuleItemListFragment.EXTRA_LIST";
private static final String EXTRA_MODULE = "ModuleItemListFragment.EXTRA_MODULE";
public static ModuleItemListFragment instantiate(ArrayList<ModuleItem> list, Module mod) {
final Bundle args = new Bundle();
args.putParcelable(EXTRA_LIST, list);
args.putParcelable(EXTRA_MODULE, module);
final ModuleItemListFragment f = new ModuleItemListFragment();
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
final Bundle args = getArguments();
this.list = args.getParcelable(EXTRA_LIST);
this.module = args.getParcelable(EXTRA_MODULE);
}
Of course, you have to make your Module Parcelable or Serializable.
You must specify args because the Fragment can be killed and restored by the system and if you pass data via setters or constructors they will not be restored and therefore can become null in some circumstances.
Custom Adapter getView() method is not called
The only reasons getView
is not called are:
getCount
returns 0.- you forget to call
setAdapter
on theListView
. - If the
ListView
's visibility (or its container's visibility) isGONE
. Thanks to @TaynãBonaldo for the valuable input. ListView
is not attached to any viewport layout. That is,mListView = new ListView(...)
is used withoutmyLayout.addView(mListView)
.
In the onPostExcute
, after you create a new instance of CarListAdapter
I will suggest you to update the new instance to your ListView
. Indeed you need to call again
mList.setAdapter(adapter);
Edit: setAdapter
should be always called on the ui thread, to avoid unexpected behaviours
Edit2:
The same applies to RecyclerView
. Make sure that
getItemCount
is returning a value grater than0
(usually the dataset size)- both
setLayoutManager
andsetAdapter
have to be called on theUI Thread
- The visibility of the widget has to be set to
VISIBLE
How Android Custom Adapter works?
I think this link can help you. getview is a callback function which will be called automatically when you will display your listview on Activity. When you display your listview then you overrides getview and inflates your row from XML or dynamically creates your row. That row you return as a view which displays in your listview.
How does the getView() method work when creating your own custom adapter?
For each row getview will be called once. You create your layouts and return them as view. Those respective views displays in your lisview rows.
Related Topics
Progressbar Togther with Asynctask
Phonegap/Cordova Android Development
How to Change the Package Name of an Android App on Google Play
Android: Using Simplecursoradapter to Get Data from Database to Listview
Android Share Images from Assets Folder
Checkselfpermission Method Is Not Working in Targetsdkversion 22
Best Practices: Layouts on Android (Programmatic VS Xml)
App Not Run in Visual Studio Emulator for Android in Visual Studio 2015
What File System Path Is Used by Android's Context.Openfileoutput()
Android - Key Dispatching Timed Out
Manifest Merger Failed Targeting Android 12
Android:Maximum Allowed Width & Height of Bitmap
Quaternion Rotation Does Not Work as Excepted