There is a BaseAdapter based BaseAdapter :
public class ContactsListAdapter extends BaseAdapter{ private LayoutInflater inflater; private ArrayList<ContactsListItems> mContactsList = new ArrayList<>(); ContactsListAdapter(Context context, ArrayList<ContactsListItems> users){ mContactsList = users; inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return mContactsList.size(); } @Override public Object getItem(int i) { return mContactsList.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View convertView, ViewGroup viewGroup) { View view = convertView; ViewHolder holder; ContactsListItems user = getUser(i); if (view == null){ holder = new ViewHolder(); if (user.getUIN() == -9){ view = inflater.inflate(R.layout.contacts_list_header, viewGroup, false); //((TextView)view.findViewById(R.id.twGroupName_header)).setText(user.getGroupName()); holder.twGroupName_header = (TextView)view.findViewById(R.id.twGroupName_header); holder.twGroupName_header.setText(user.getGroupName()); view.setTag(R.id.group_id_contacts_listview, -1); view.setTag(R.id.parent_group_id_contacts_lisview, user.getParentId()); }else { if (!user.ismIsGroup()) { view = inflater.inflate(R.layout.item_people_in_contacts, viewGroup, false); // ((TextView) view.findViewById(R.id.twContactName)).setText(user.getDisplayName()); // ((TextView) view.findViewById(R.id.twUIN)).setText("UIN:" + user.getUIN().toString()); holder.twContactName = (TextView)view.findViewById(R.id.twContactName); holder.twContactName.setText(user.getDisplayName()); holder.twUIN = (TextView)view.findViewById(R.id.twUIN); holder.twUIN.setText("UIN:" + user.getUIN().toString()); view.setTag(R.id.group_id_contacts_listview, user.getGroupId()); } else { view = inflater.inflate(R.layout.item_group_in_contacts, viewGroup, false); //((TextView) view.findViewById(R.id.twGroupName_contacts)).setText((user.getGroupName())); holder.twGroupName_contacts = (TextView)view.findViewById(R.id.twGroupName_contacts); holder.twGroupName_contacts.setText(user.getGroupName()); view.setTag(R.id.group_id_contacts_listview, user.getGroupId()); } } view.setTag(holder); } else { holder = (ViewHolder)view.getTag(); } return view; } private ContactsListItems getUser(int position) { return ((ContactsListItems) getItem(position)); } private static class ViewHolder{ TextView twContactName; TextView twUIN; TextView twGroupName_contacts; TextView twGroupName_header; } } And the fragment in which ListView is filled with data:
public class Contacts extends Fragment { public ContactsListAdapter adapter; ArrayList<ContactsListItems> items = new ArrayList<>(); String CONTACTS_LIST = "contacts_list"; @Override public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_contacts, container, false); SharedPreferences spref = MainPage.contextOfApplication.getSharedPreferences(Consts.APP_PREFERENCES, MainPage.MODE_PRIVATE); final String sData = spref.getString(CONTACTS_LIST, ""); ContactsListItems Item; try { JSONArray contactsListJson = new JSONArray(sData); for (int i=0; i<contactsListJson.length(); i++){ JSONObject user = contactsListJson.getJSONObject(i); if (user.getBoolean("IsGroup") && user.getInt("ParentID") == 0) { Item = new ContactsListItems(user.getInt("UIN"), user.getInt("Sex"), user.getInt("ParentID"), user.getInt("ID"), user.getString("DisplayName"), user.getString("GroupName"), user.getBoolean("TeamLead"), user.getBoolean("IsGroup"), user.getInt("GroupID")); items.add(Item); } } }catch (JSONException e){ } adapter = new ContactsListAdapter(getActivity(), items); final ListView listView = (ListView)view.findViewById(R.id.lwContacts); listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { Integer GroupId = (Integer) view.getTag(R.id.group_id_contacts_listview); Integer parentGroupId = (Integer) view.getTag(R.id.parent_group_id_contacts_lisview); ContactsListItems ItemsOnClick; ArrayList<ContactsListItems> itemsOnClick = new ArrayList<>(); //------------------------------Обработка нажатия на группу------------------------------------- if (GroupId > 0) { try { JSONArray contactsListJson = new JSONArray(sData); for (int j = 0; j < contactsListJson.length(); j++) { JSONObject user = contactsListJson.getJSONObject(j); if (user.getInt("GroupID") == GroupId){ ContactsListItems headerItem = new ContactsListItems(-9,0,user.getInt("ParentID"),0,"", user.getString("GroupName"), false, false, user.getInt("GroupID")); itemsOnClick.add(headerItem); } if (user.getInt("ParentID") == GroupId) { ItemsOnClick = new ContactsListItems(user.getInt("UIN"), user.getInt("Sex"), user.getInt("ParentID"), user.getInt("ID"), user.getString("DisplayName"), user.getString("GroupName"), user.getBoolean("TeamLead"), user.getBoolean("IsGroup"), user.getInt("GroupID")); itemsOnClick.add(ItemsOnClick); } } } catch (JSONException e) { e.printStackTrace(); } ContactsListAdapter onClickAdapter = new ContactsListAdapter(getActivity(), itemsOnClick); listView.setAdapter(onClickAdapter); //------------------------------Обработка нажатия на группу------------------------------------- } else //------------------------------Обработка нажатия на контакт------------------------------------- if (GroupId == 0){ Toast t = Toast.makeText(getActivity(), "Contact", Toast.LENGTH_SHORT); t.show(); //------------------------------Обработка нажатия на контакт------------------------------------- } else //------------------------------Обработка нажатия на header-------------------------------------- if (GroupId == -1){ ArrayList<ContactsListItems> itemsOnBackClick = new ArrayList<>(); try { JSONArray backJson = new JSONArray(sData); ContactsListItems ItemsOnBackClick; for (int k=0; k<backJson.length(); k++){ JSONObject backUser = backJson.getJSONObject(k); if ((backUser.getInt("GroupID") == parentGroupId) && parentGroupId != 0){ ContactsListItems headerItem = new ContactsListItems(-9,0,backUser.getInt("ParentID"),0,"", backUser.getString("GroupName"), false, false, backUser.getInt("GroupID")); itemsOnBackClick.add(headerItem); } if (backUser.getInt("ParentID") == parentGroupId) { ItemsOnBackClick = new ContactsListItems(backUser.getInt("UIN"), backUser.getInt("Sex"), backUser.getInt("ParentID"), backUser.getInt("ID"), backUser.getString("DisplayName"), backUser.getString("GroupName"), backUser.getBoolean("TeamLead"), backUser.getBoolean("IsGroup"), backUser.getInt("GroupID")); itemsOnBackClick.add(ItemsOnBackClick); } ContactsListAdapter onBackClickAdapter = new ContactsListAdapter(getActivity(), itemsOnBackClick); listView.setAdapter(onBackClickAdapter); } }catch (JSONException e){ e.printStackTrace(); } } //------------------------------Обработка нажатия на header-------------------------------------- } }); return view; } } I am trying to implement a multi-level list. With a small number of elements, everything works well, but as soon as there are more elements than can fit on the phone’s screen, scrolling through the ListView causes the elements to shuffle. The functionality that is embedded in them is preserved, but there is no order.
Maybe someone has an idea why?
Changed the getView () method as follows:
public View getView(int i, View convertView, ViewGroup viewGroup) { View view = convertView; ViewHolder holder; ContactsListItems user = getUser(i); if (view == null){ holder = new ViewHolder(); if (user.getUIN() == -9){ view = inflater.inflate(R.layout.contacts_list_header, viewGroup, false); holder.twGroupName_header = (TextView)view.findViewById(R.id.twGroupName_header); view.setTag(R.id.group_id_contacts_listview, -1); view.setTag(R.id.parent_group_id_contacts_lisview, user.getParentId()); }else { if (!user.ismIsGroup()) { view = inflater.inflate(R.layout.item_people_in_contacts, viewGroup, false); holder.twContactName = (TextView)view.findViewById(R.id.twContactName); holder.twUIN = (TextView)view.findViewById(R.id.twUIN); view.setTag(R.id.group_id_contacts_listview, user.getGroupId()); } else { view = inflater.inflate(R.layout.item_group_in_contacts, viewGroup, false); holder.twGroupName_contacts = (TextView)view.findViewById(R.id.twGroupName_contacts); view.setTag(R.id.group_id_contacts_listview, user.getGroupId()); } } view.setTag(holder); } else { holder = (ViewHolder)view.getTag(); } if (user.getUIN() == -9){ holder.twGroupName_header.setText(user.getGroupName()); }else { if (!user.ismIsGroup()) { holder.twContactName.setText(user.getDisplayName()); holder.twUIN.setText("UIN:" + user.getUIN().toString()); } else { holder.twGroupName_contacts.setText(user.getGroupName()); } } return view; } But now when scrolling, when I reach the end of the list, an error flies:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
getView(...)method ifview != nullyou do not link any data to theviewelement. - post_zeewgetView()crashif (view == null){along with its alternative branch and see what happens. - tseViewHolderpattern - that is, reuse the already createdView. In case you need to create a newView, you create it and fill it with data. In case the oldViewcomes togetView(...), which needs to be updated (that is, whenview != null), you do not update it, that is, do not fill it with some new (other) data. - post_zeew