I meet a something wrong about IndexOutOfBoundsException - android

I have a Json data like ,I want to show the information in my listView so I parse them into a ArrayList<String> and then add to the adapter.
{
"areas": [
{
"fieldTag": "1",
"areaId": 2,
"areaName": "No.1",
"devices": [
{
"cameraName": "A",
"busyFields": "null",
"freeFields": "No.1,NO,2",
},{
"cameraName": "B"
"busyFields": "null",
"freeFields": "No.3,No.4",
}
]
}
],
"error": 0,
"message": "ok"
}
and I use Gson to parse it and I make the data to a list for show them in the Adapter,my code is :
if (mDeviceInfo.getError() == 0) {
for (int i = 0; i<mDeviceInfo.getAreas().size();i++){
adapter.addSectionHeaderItem(mDeviceInfo.getAreas().get(i).getAreaName());
for (int k = 0; k<mDeviceInfo.getAreas().get(i).getDevices().size();k++){
adapter.addItem(mDeviceInfo.getAreas().get(i).getDevices().get(k).getCameraName());
mPositionList.add(mDeviceInfo.getAreas().get(i).getDevices().get(k).getPosition());
mFreeFieldsList.add(mDeviceInfo.getAreas().get(i).getDevices().get(k).getFreeFields());
mBusyFieldsList.add(mDeviceInfo.getAreas().get(i).getDevices().get(k).getBusyFields());
}
}
adapter.addMessage(mPosition,mFreeFields,mBusyFields);
}else {
Toast.makeText(this,"get info failed",Toast.LENGTH_SHORT).show();
}
and that is my code as the Adapter:
public class CameraListAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private ArrayList<String> mData = new ArrayList<String>();
private ArrayList<String> mPosition = new ArrayList<>();
private ArrayList<String> mFreeFields = new ArrayList<>();
private ArrayList<String> mBusyFields = new ArrayList<>();
private TreeSet<Integer> sectionHeader = new TreeSet<Integer>();
private LayoutInflater mInflater;
public CameraListAdapter(Context context) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSectionHeaderItem(final String item) {
mData.add(item);
sectionHeader.add(mData.size() - 1);
notifyDataSetChanged();
}
public void addMessage(ArrayList<String> position,ArrayList<String> freeFields,ArrayList<String> busyFields){
mPosition = position;
mFreeFields = freeFields;
mBusyFields = busyFields;
}
#Override
public int getItemViewType(int position) {
return sectionHeader.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean isEnabled(int position) {
return getItemViewType(position) != TYPE_SEPARATOR;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
int rowType = getItemViewType(position);
if (convertView == null) {
viewHolder = new ViewHolder();
switch (rowType) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.cameradetail, null);
viewHolder.mCameraName = (TextView) convertView.findViewById(R.id.cameraName);
Log.d("CameraListAdapter","position "+position);
viewHolder.mCameraName.setText(mData.get(position));
viewHolder.position = (TextView) convertView.findViewById(R.id.cameraposition);
viewHolder.position.setText(mPosition.get(position));
viewHolder.busyFields = (TextView) convertView.findViewById(R.id.busyfields);
viewHolder.busyFields.setText(mBusyFields.get(position));
viewHolder.freeFields = (TextView) convertView.findViewById(R.id.freefields);
viewHolder.freeFields.setText(mFreeFields.get(position));
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.cameratag, null);
viewHolder.mTag = (TextView) convertView.findViewById(R.id.areaName);
viewHolder.mTag.setText(mData.get(position));
break;
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
public static class ViewHolder {
public TextView mTag;
public TextView mCameraName;
public TextView position;
public TextView busyFields;
public TextView freeFields;
}
}
But it always show me that
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at .CameraListAdapter.getView(CameraListAdapter.java:106)
It upset me for 2 days so are there anyone to help me ?Thank you so much

In an Adapter, the size of the data is determined by getCount, which you defined like so.
#Override
public int getCount() {
return mData.size();
}
This means that the range of positions in getView is 0 to the value returned by getCount.
But, you seem to have 4 lists of various sizes, or at least not the same size as mData
private ArrayList<String> mData = new ArrayList<String>();
private ArrayList<String> mPosition = new ArrayList<>();
private ArrayList<String> mFreeFields = new ArrayList<>();
private ArrayList<String> mBusyFields = new ArrayList<>();
I'm not sure which one is causing the problem, but, for example, this will throw an exception if mPosition doesn't hold the same amount of data as mData
viewHolder.position.setText(mPosition.get(position));
I would recommend you not have 4 separate String Arraylists since that data seems to pertain to a single Object, which if you want a proper custom Adapter, you give it a list of your Object type (parsed from Gson, for example) instead of individual pieces of an Object

When you use
#Override
public int getCount() {
return mData.size();
}
you basically tell the adapter to call the getView() method for every item in you mData list. The position argument in your getView() method corresponds to the entry in your mData list. You then use that same position argument to get data out of three other lists that are probably of different size than the mData list so one of the get(position) calls on one of the other lists will throw the exception you are seeing. This can be easily debugged if you use the debugger in Android Studio on line 106 in your adapter.

Related

How to add a list of image from drawable into an arraylist using ID from a string-arrays

Here's my code, please help check my problem
My string list that has the same name with the images in res drawable:
<resources>
<string name="app_name">Intent Practice 1</string>
<string-array name="list_name">
<item>akiza</item>
<item>blueeyes</item>
<item>buster</item>
<item>cyberdragon</item>
<item>darklaw</item>
<item>darkmagician</item>
<item>darkmagiciangirl</item>
<item>darkpaladin</item>
<item>dragunity</item>
<item>exodia</item>
<item>gaia</item>
<item>galaxyeyes</item>
<item>harpies</item>
<item>hope</item>
<item>joey</item>
<item>junk</item>
<item>kaibaseto</item>
<item>marik</item>
<item>neos</item>
<item>redeyes</item>
<item>shaddoll</item>
<item>shiningflare</item>
<item>skulled</item>
<item>spear</item>
<item>stardust</item>
<item>tourguide</item>
<item>wingeddragon</item>
<item>yamiyugi</item>
<item>yudai</item>
<item>yugimuto</item>
<item>yuma</item>
<item>yusei</item>
<item>question</item>
</string-array>
</resources>
I can set an ImageView using
ImageView imgQuestion, imgAnswer, temp;
static ArrayList<String> arrayName;
public static ArrayList<HinhAnh> arrayImg;
String questionName;
int REQUEST_CODE_IMG = 2703;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgAnswer = findViewById(R.id.imgAnswer);
imgQuestion = findViewById(R.id.imgQuestion);
String[] mangTen = getResources().getStringArray(R.array.list_name);
arrayName = new ArrayList<>(Arrays.asList(mangTen));
arrayImg = new ArrayList<>();
Collections.shuffle(arrayName);
**int idImg = getResources().getIdentifier(arrayName.get(1), "drawable", getPackageName());
imgQuestion.setImageResource(idImg);**
But I dont know how to add the list of images in to the arrayImg, I used:
for (int position = 0; position < arrayName.size(); position++){
int id = getResources().getIdentifier(arrayName.get(position), "drawable", getPackageName());
arrayImg.add(new HinhAnh(arrayName.get(position) + "", id));
Toast.makeText(this, arrayImg.get(1).getTen() + "", Toast.LENGTH_SHORT).show();
}
I used Toast to check if I add successfully then the error showed out
Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.get(ArrayList.java:437)
at com.example.intentpractice.MainActivity.onCreate(MainActivity.java:38)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
My class HinhAnh
public class HinhAnh {
private String Ten;
private int Hinh;
public HinhAnh(String ten, int hinh) {
Ten = ten;
Hinh = hinh;
}
public String getTen() {
return Ten;
}
public void setTen(String ten) {
Ten = ten;
}
public int getHinh() {
return Hinh;
}
public void setHinh(int hinh) {
Hinh = hinh;
}
}
They all lead to my adapter is null then I cannot fill my gridview at all. Please help!!
Edit:
I changed the line to get(position) then it worked. But it still showed error point to my adapter, here's my adapter:
public class ImageAdapter extends BaseAdapter {
private Context context;
private int layout;
private List<HinhAnh> imageList;
public ImageAdapter(Context context, int layout, List<HinhAnh> imageList) {
this.context = context;
this.layout = layout;
this.imageList = imageList;
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder{
ImageView imgHinh;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(layout, null);
holder.imgHinh = convertView.findViewById(R.id.imgItem);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.imgHinh.setImageResource(imageList.get(position).getHinh());
return convertView;
}
}
and where I called it
adapter = new ImageAdapter(this, R.layout.imageline, MainActivity.arrayImg);
gridView.setAdapter(adapter);
The error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference
at com.example.intentpractice.Answers.onCreate(Answers.java:18)
Solved, I forgot returning getCount to array.size().
Thanks all!!!
There is a issue in your for loop for adding the images into the list.
For the position 0, there will be only one element in the arrayImg but you are calling arrayImg.get(1) which is causing java.lang.IndexOutOfBoundsException
change that line to:
for (int position = 0; position < arrayName.size(); position++){
int id = getResources().getIdentifier(arrayName.get(position), "drawable", getPackageName());
arrayImg.add(new HinhAnh(arrayName.get(position) + "", id));
Toast.makeText(this, arrayImg.get(position).getTen() + "", Toast.LENGTH_SHORT).show();
}

How to get listview items both visible and invisible child values

This loop return only visible position values.However I need the values of child items that are invisible.
for (int i = 0; i < material_issue_list.getCount(); i++) {
View layout = materialIssueAdapter.getViewByPositio(i, material_issue_list);
LinearLayout listItem = (LinearLayout) materialIssueAdapter.getViewByPositio(i, material_issue_list);
String batchSTR = ((AutoCompleteTextView) listItem.findViewById(R.id.batch_AutoComplete)).getText().toString();
String qtySTR = ((EditText) listItem.findViewById(R.id.issue_qty_ETD)).getText().toString();}
My full adapter class,Some one help me suggest to get the correct output.My problem I'm getting null values from the views that are invisible.
Only the visible values are being updated to arraylist.
Thanks in advance.
public class IssueMaterialAdapter extends BaseAdapter {
private Activity activity;
public static ArrayList Dummylist;
private static LayoutInflater inflater = null;
public Resources res;
public static ArrayList<BatchNav> batchNavs_Arr;
static ArrayList<String> batch_Arr;
public static ArrayList<String> batch_data;
public static ArrayList<String> issue_qty;
LinkedHashSet<String> hashSet;
public static ArrayList<BatchModel> batchModels = new ArrayList<BatchModel>();
public static HashMap<ViewHolder, String> batch_map;
public static HashMap<ViewHolder, String> qty_map;
HashMap<String, String> mValues = new HashMap<String, String>();
ArrayList<SaveDataModel> saveDataModels;
public IssueMaterialAdapter(Activity a, ArrayList dummy) {
activity = a;
Dummylist = dummy;
loadBatch();
this.batch_map = new HashMap<>();
inflater = (LayoutInflater) activity.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
if (Dummylist.size() <= 0)
return 1;
return Dummylist.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.material_issue_details_list, null);
holder = new ViewHolder();
holder.batch = (AutoCompleteTextView) vi.findViewById(R.id.batch_AutoComplete);
holder.issue = (EditText) vi.findViewById(R.id.issue_qty_ET);
holder.material_descrption = (TextView) vi.findViewById(R.id.material_desc);
holder.unit_issue = (EditText) vi.findViewById(R.id.unit_issue_ET);
holder.matnr = (TextView) vi.findViewById(R.id.matnr);
holder.prdgrp = (TextView) vi.findViewById(R.id.prod_grp);
vi.setTag(holder);
batch_map.put(holder, "");
FilterWithSpaceAdapter<String> farmer_co_no_adapter = new FilterWithSpaceAdapter<String>(activity,
R.layout.custom_items, batch_Arr);
holder.batch.setAdapter(farmer_co_no_adapter);
holder.batch.setThreshold(1);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
if (Dummylist.size() == AgriDistributionActivity.get_materials.size()) {
holder.material_descrption.setText(AgriDistributionActivity.get_materials.get(position));
holder.matnr.setText(AgriDistributionActivity.get_matnr.get(position));
holder.prdgrp.setText(AgriDistributionActivity.selected_prdgrp.get(position));
}
try {
if (saveDataArr.size() > 0) {
holder.batch.setText(saveDataArr.get(position).getBatch());
holder.issue.setText(saveDataArr.get(position).getQty());
holder.unit_issue.setText(saveDataArr.get(position).getQty_uom());
}
} catch (Exception e) {
}
return vi;
}
public static class ViewHolder {
public EditText issue, unit_issue;
public AutoCompleteTextView batch;
public TextView material_descrption, matnr,prdgrp;
}
private void loadBatch() {
batch_Arr = new ArrayList<String>();
batchNavs_Arr = new ArrayList<BatchNav>();
hashSet = new LinkedHashSet<>();
BatchNavEntityCollection batchNavEntityCollection = BatchNavEntityCollection.getInstance();
batchNavs_Arr = batchNavEntityCollection.getBatchOutVal();
for (int i = 0; i < batchNavs_Arr.size(); i++) {
String batch = batchNavs_Arr.get(i).getCharg();
batch_Arr.add(batch);
hashSet.addAll(batch_Arr);
batch_Arr.clear();
batch_Arr.addAll(hashSet);
}
}
public View getViewByPositio(int position, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (position < firstListItemPosition || position > lastListItemPosition) {
return listView.getAdapter().getView(position, null, listView);
} else {
final int childIndex = position - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
}
You have saveDataArr list which holds all your data.
You can add a getter if you want to do it from an activity , add something like this to your adapter :
private SaveDataModelsendLog(int position) {
return saveDataArr(position);
}
That should do the trick , having said all that you should also look at the difference between static and non-static variables ,
it seems like you have to many of them ,
Enjoy.

Android Custom ListView onClickListener returns null

Something very strange is happening with my custom ListView. After the list is loaded if I click on the ListItems very fast it crashes but if I give it a second then everything works fine.
My list contains section headings (see screenshot) which changes the position of the UI list from the Model List. So when I populate the ListView I do the mapping in the listAdapter class and I believe this is causing the code the crash. I click on the view before the mapping is complete and I get a "Value" of null for the given key.
public class ListAdapter extends BaseAdapter implements SectionIndexer {
private Context mContext;
private static final String TAG = "ListAdapter";
private LayoutInflater mInflater;
private ArrayList mData = new ArrayList();
// MapIndex to map the scroll alphabet to section
private HashMap<String, Integer> mapIndex;
// To return the right index otherwise the click will return wrong objects becasue the count the section headers
private ConcurrentHashMap<Integer, Integer> viewPositions;
// contains all the sections alphabets
private String[] sections;
/** Int code to represent regular list items **/
public static final int TYPE_ITEM = 0;
/** Int val to represent header list item **/
private static final int TYPE_SEPARATOR = 1;
/** There are two different items **/
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private static TextView name;
private static TextView industry;
private static UserModel user;
private ImageView logo;
private static int mCount = 0;
public ListAdapter(Context context, ArrayList<UserModel> users) {
Collections.sort(users, UserModel.Comparators.NAME);
viewPositions = new ConcurrentHashMap<Integer, Integer>();
mContext = context;
mInflater = ((Activity)mContext).getLayoutInflater();
mapIndex = new LinkedHashMap<String, Integer>();
for (int i = 0; i < users.size(); i++){
String ch = users.get(i).getFirstName().substring(0,1);
ch.toUpperCase();
/** If HashMap doesn't have the Alphabet put the new one **/
if (!mapIndex.containsKey(ch)){
mapIndex.put(ch, i);
addSeparatorItem(ch);
mCount ++;
}
addItem(users.get(i));
viewPositions.put(mCount,i);
mCount ++;
}
Set<String> sectionLetters = mapIndex.keySet();
sections = new String[sectionLetters.size()];
sectionLetters.toArray(sections);
}
public int getRealPosition(int key){
Log.d(TAG, "getRealPosition: Key = " + key + "Value = " + viewPositions.get(key));
return viewPositions.get(key);
}
public void addItem(final UserModel item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
if (mData.get(position) instanceof UserModel){
return TYPE_ITEM;
}
return TYPE_SEPARATOR;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
switch (type) {
case TYPE_ITEM:
user = ((UserModel)mData.get(position));
convertView = mInflater.inflate(R.layout.fragment_contact_list, null);
name = (TextView) convertView.findViewById(R.id.list_contactName);
name.setText(user.getFirstName() + " " + user.getLastName());
industry = (TextView) convertView.findViewById(R.id.list_industry);
industry.setText(user.getIndustry());
logo = (ImageView) convertView.findViewById(R.id.list_logo);
break;
case TYPE_SEPARATOR:
TextView seperator = (TextView) mInflater.inflate(R.layout.list_header, null);
seperator.setText(mData.get(position).toString());
seperator.setClickable(false);
seperator.setBackgroundColor(mContext.getResources().getColor(R.color.blue));
convertView = seperator;
break;
}
return convertView;
}
/********************* SectionIndexer Methods ***********************/
#Override
public Object[] getSections() {
return sections;
}
#Override
public int getPositionForSection(int sectionIndex) {
return mapIndex.get(sections[sectionIndex]);
}
#Override
public int getSectionForPosition(int position) {
return 0;
}
}
public class ContactListActivity extends AppCompatActivity {
private ArrayList<UserModel> mUserList;
private ListAdapter adapter;
private IndexableListView mListView;
public static final String CONTACT_FRAGMENT = "ContactFragment";
#Override
public void onCreate(Bundle savedInstances) {
super.onCreate(savedInstances);
setContentView(R.layout.list_layout);
//setHasOptionsMenu(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mUserList = UserList.get(this).getUserList();
Collections.sort(mUserList, UserModel.Comparators.NAME);
mListView = (IndexableListView) findViewById(R.id.listview);
adapter = new ListAdapter(this, mUserList);
mListView.setAdapter(adapter);
mListView.setFastScrollEnabled(true);
mListView.setDivider(null);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (adapter.getItemViewType(position) == adapter.TYPE_ITEM) {
Intent intent = new Intent(view.getContext(), ContactActivity.class);
intent.putExtra(HomeFragment.LAUNCH_FRAGMENT, CONTACT_FRAGMENT);
intent.putExtra("userId", adapter.getRealPosition(position));
startActivity(intent);
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sort_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.sortName){
Log.d("Sort ", "Sort by Name Clicked");
}
return super.onOptionsItemSelected(item);
}
}
12-10 09:47:39.951 17995-17995/com.example.macintosh.klickcard D/ListAdapter: getRealPosition: Key = 6Value = null
12-10 09:47:39.971 17995-17995/com.example.macintosh.klickcard D/AndroidRuntime: Shutting down VM
12-10 09:47:39.981 17995-17995/com.example.macintosh.klickcard E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.macintosh.klickcard, PID: 17995
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at com.example.macintosh.klickcard.Helpers.ListAdapter.getRealPosition(ListAdapter.java:83)
at com.example.macintosh.klickcard.ContactListActivity$1.onItemClick(ContactListActivity.java:52)
at android.widget.AdapterView.performItemClick(AdapterView.java:339)
at android.widget.AbsListView.performItemClick(AbsListView.java:1544)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3721)
at android.widget.AbsListView$3.run(AbsListView.java:5660)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6837)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
You are creating new View element in your ListAdapter getView method every time, that might be the reason of crash. You can make use of previously created view element.
public View getView(int position, View convertView, ViewGroup parent) {
// Create view element only if convertView is null
if (convertView == null) {
LayoutInflater inflater = context.getLayoutInflater();
convertView= inflater.inflate(YOUR_XML_RESOURCE_ID, parent, false);
}
// Populate convertView with necessary details
return convertView;
}
It took me a while to figure this out. Couple of things I found out was that don't check if convert view is null, because it messes up the organization of the list. Second was not to use a hashmap because the adapter class gets called in random times and you are mapping to wrong positions hence the null pointer exception. The trick is this method. Nothing mind blowing just a plain index shift.
public int getRealPosition(int key){
user = (UserModel) getItem(key);
String ch = user.getFirstName().substring(0,1);
for (int i = 0; i < sections.length; i++) {
if (ch.equalsIgnoreCase(sections[i])) {
return key - (i + 1);
}
}
return -1;
}

ListView items repetition

Now I have a list view with a custom adapter which shows a different layout types.
List view items are repeating in a random manner and I can't figure out the problem.
So, can anybody help please?
Here is my code.
public class NewsFeedAdapter extends BaseAdapter {
private final int IMAGE_COMPARISON = 0;
private final int POLL = 1;
private final int EMO = 2;
private final int TYPE_MAX_COUNT = EMO + 1;
private ArrayList<Post> posts = new ArrayList<Post>();
private ArrayList<Post> originalPosts = new ArrayList<Post>();
private MaterialDialog alert;
private Context context;
private ApiClient apiClient;
private SharedPreferences sharedPreferences;
private int id;
private Bitmap bitmap;
private ArrayList<View> views ;
private Intent sharingIntent;
private String link;
private String type;
public NewsFeedAdapter(Context context, ArrayList<Post> questionItems) {
this.context = context;
this.posts = questionItems;
this.originalPosts = new ArrayList<Post>(posts);
this.apiClient = ApiClient.getInstance(context);
sharedPreferences = context.getSharedPreferences(context.getResources().getStringArray(R.array.preferences)[4], 0);
views = new ArrayList<>();
}
#Override
public int getCount() {
return posts.size();
}
#Override
public Object getItem(int position) {
return posts.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
#Override
public int getItemViewType(int position) {
String type = ((Post)getItem(position)).getQ().getType();
if(type.equalsIgnoreCase("radio")){
return POLL;
}else if(type.equalsIgnoreCase("image")){
return IMAGE_COMPARISON;
}else{
return EMO;
}
}
public int getItemViewType(Post post) {
String type = (post).getQ().getType();
if(type.equalsIgnoreCase("radio")){
return POLL;
}else if(type.equalsIgnoreCase("image")){
return IMAGE_COMPARISON;
}else{
return EMO;
}
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
switch (type) {
case IMAGE_COMPARISON:
ImageListRowView imageListRowView;
// if (convertView == null) {
imageListRowView = new ImageListRowView(context, new MenuListener() {
#Override
public void onReceive(MenuItemAction menuItemAction,int position) {
preformMenuAction(menuItemAction, position);
}
});
imageListRowView.setData(posts.get(position));
imageListRowView.setTag(R.string.view_tag,position);
views.add(imageListRowView);
return imageListRowView;
// }
// else
// imageListRowView = (ImageListRowView) convertView;
//return imageListRowView;
{
case EMO:
EmoListRowView emoListRowView;
// if (convertView == null) {
emoListRowView = new EmoListRowView(context, new MenuListener() {
#Override
public void onReceive(MenuItemAction menuItemAction,int position) {
preformMenuAction(menuItemAction, position);
}
});
emoListRowView.setData(posts.get(position));
emoListRowView.setTag(R.string.view_tag,position);
views.add(emoListRowView);
return emoListRowView;
// }
// else
// emoListRowView = (EmoListRowView) convertView;
// return emoListRowView;
case POLL:
PollListRowView pollListRowView;
// if (convertView == null) {
pollListRowView = new PollListRowView(context, new MenuListener() {
#Override
public void onReceive(MenuItemAction menuItemAction,int position) {
preformMenuAction(menuItemAction, position);
}
});
pollListRowView.setData(posts.get(position));
pollListRowView.setTag(R.string.view_tag,position);
views.add(pollListRowView);
return pollListRowView;
}
// else
// pollListRowView = (PollListRowView) convertView;
// return pollListRowView;
}
return convertView;
}
getView() needs to always customize the rows. The only variance based upon whether convertView is null is whether you have to also inflate the rows.
In each of your case blocks, if convertView is not null, you just return convertView without modification.
give a look at the following question.I think your problem resembles this one.
After scrolling listview, listview items getting repeatedly in android

How to pass Hashmap data to BaseAdapter in Android

I am currently implementing Sectioned Listview Adapter PinnedSectioned Listview
Currently i have changed the implementation to base adapter but I am facing some problem in passing the values to the base adapter
How can I pass Hashmap value to the adapter.
Example-
HashMap<Integer, ArrayList<Test>> example = new HashMap<Integer, ArrayList<Test>>();
Base Adapter implementation
static class MyPinnedSectionListAdapter extends BaseAdapter implements PinnedSectionListView.PinnedSectionListAdapter{
private ArrayList mList;
private Context mContext;
private LayoutInflater mInflater;
ArrayList<Item> value;
public static final int FIRST = 0;
public static final int SECOND = 1;
int size=0;
private String[] mKeys;
private Map<String, ArrayList<Item>> mData = new HashMap<String, ArrayList<Item>>();
public MyPinnedSectionListAdapter(Context context, Map<String, ArrayList<Item>> map){
mList=new ArrayList();
mData=map;
mKeys = mData.keySet().toArray(new String[mData.size()]);
for (Map.Entry<String, ArrayList<Item>> entry : map.entrySet()) {
value= entry.getValue();
size+=value.size();
System.out.println();
}
System.out.println("size" + size);
mList.addAll(map.entrySet());
this.mContext = context;
this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public boolean isItemViewTypePinned(int viewType) {
if(viewType == SECOND){
return true;
}else{
return false;
}
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(mKeys[position]);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
if(viewType == FIRST){
convertView = mInflater.inflate(R.layout.item,parent,false);
String key = mKeys[position];
String Value = getItem(position).toString();
((TextView)convertView.findViewById(R.id.textView1)).setText(Value);
}
if(viewType == SECOND){
String key = mKeys[position];
String Value = getItem(position).toString();
convertView = mInflater.inflate(R.layout.section,parent,false);
((TextView)convertView.findViewById(R.id.textView1)).setText(Value);
}
return convertView;
}
#Override
public int getItemViewType(int position) {
#SuppressWarnings("unchecked")
ArrayList<Item> item = (ArrayList<Item>) getItem(position);
if (item.get(position).type == 0){
return FIRST;
}else{
return SECOND;
}
}
#Override
public int getViewTypeCount() {
return 2;
}
}
POJO:
static class Item {
public static final int ITEM = 0;
public static final int SECTION = 1;
public final int type;
public final String text;
public int sectionPosition;
public int listPosition;
public Item(int type, String text) {
this.type = type;
this.text = text;
}
#Override public String toString() {
return text;
}
}
CODE:
HashMap> example = new HashMap>();
ArrayList<Item> test1 = new ArrayList<Item>();
test1.add( new Item(Item.SECTION, "Section1"));
test1.add( new Item(Item.ITEM, "Section2"));
test1.add( new Item(Item.ITEM, "Section3"));
ArrayList<Item> test2 = new ArrayList<Item>();
test2.add( new Item(Item.SECTION, "Section4"));
test2.add( new Item(Item.ITEM, "Section5"));
test2.add( new Item(Item.ITEM, "Section6"));
example.put("1", test1);
example.put("2", test2);
setListAdapter(new MyPinnedSectionListAdapter(this,example));
I am getting ouput like :
[Section1 , [Section 2], [Section3]
[Section 4],[Section 5],[Section 6]
Why are you not making constructor for your MyPinnedSectionListAdapter with HashMap<K,V> argument. and pass your HashMap<Integer, ArrayList<Test>> example to it,
Something like,
public MyPinnedSectionListAdapter(Context context, HashMap<Integer, ArrayList<Test>> hashMap){...}
Edit:
As per #av_lee 's comment.
You can use Guava's Multimap class
with properties like,
A key is contained in the multimap if and only if it maps to at least
one value. Any operation that causes a key to have zero associated
values has the effect of removing that key from the multimap.
The total entry count is available as size().

Categories

Resources