I deleted some items in an adapter and after my setOnClick crash - java

I'm trying to show a listView after i deleted some items. But, after i deleted some items, OnItemClick crash (java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification). I want to show a new list after i deleted, like a filter. I already try to use adapter.remove(position) and list.remove(position) like the example down.
My OnItemClick
//listView.invalidateViews();
//listView.refreshDrawableState();
//pullToRefresh.setRefreshing(false);
Collections.sort(lista, new Viagem());
adapter.notifyDataSetChanged();
System.out.println(position);
Viagem vg = (Viagem) parent.getItemAtPosition(position);
Bundle bundle = new Bundle();
bundle.putString("usuario", usuario);
bundle.putString("usuarioViagem", vg.getUsuario());
bundle.putString("data", vg.getData());
bundle.putString("hora", vg.getHora());
Intent intent = new Intent(getApplicationContext(), MostraInfoViagemActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
});
How i deleted some items.
public void delete(){
jaEntrou = false;
ArrayList <Integer> apagar = new ArrayList<>();
Viagem aux;
List<String> listaUsuarios;
for(int i = 0 ; i < lista.size(); i++){
jaEntrou = false;
aux = lista.get(i);
listaUsuarios = aux.getUsuarios();
for(int j = 0; j < listaUsuarios.size(); j++){
if(listaUsuarios.get(j).equals(usuario)){
jaEntrou = true;
}
}
if(!jaEntrou){
apagar.add(i);
}
}
for(int i = apagar.size() - 1; i >= 0; i--){
int index = apagar.get(i);
lista.remove(index);
//adapter.removeItem(apagar.get(i));
//adapter.notifyDataSetChanged();
}
adapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();
lista = fb.getLista();
Intent intent = new Intent(getApplicationContext(), OnlyDelay.class);
startActivity(intent);
}
My Custom List
package com.example.caronassuldeminas;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class Custom_List extends BaseAdapter {
private List<Viagem> viagens;
private Activity act;
private Object orig;
public Custom_List(List<Viagem> viagens, Activity act){
this.viagens = viagens;
this.act = act;
}
#Override
public int getCount() {
return viagens.size();
}
#Override
public Object getItem(int position) {
return viagens.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
public void removeItem(int position){
viagens.remove(position);
}
public void attLista(List<Viagem> viagens){
this.viagens = viagens;
}
public Viagem getViagem(int position){
return viagens.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = act.getLayoutInflater().inflate(R.layout.list_item, parent, false);
TextView cidadePartida = (TextView) view.findViewById(R.id.textView8);
TextView cidadeChegada = (TextView) view.findViewById(R.id.textView9);
TextView dia = (TextView) view.findViewById(R.id.textView10);
TextView hora = (TextView) view.findViewById(R.id.textView11);
cidadePartida.setText(viagens.get(position).getCidadePartida());
cidadeChegada.setText(viagens.get(position).getCidadeChegada());
dia.setText("Dia: " + viagens.get(position).getData());
hora.setText("Hora: " + padronizaHora(viagens.get(position).getHora()) + "h");
return view;
}
public String padronizaHora(String data){
if(data.length() == 5)
return data;
int pos = 0;
String resu = "";
for(int i = 0; i < data.length(); i++){
if(data.charAt(i) == ':'){
pos = i;
break;
}
}
if(pos < 2){
resu += "0";
}
resu += data.substring(0, pos);
resu += ":";
if(data.charAt(data.length()-1) == '0'){
resu += "0";
}
resu += data.substring(pos + 1);
return resu;
}
}

Usually, when I add or remove items from the ArrayList that drives the ListView and Adapter, I recreate the adapter and re-assign it to the ListView rather than call notifyDatasetChanged. This also seems to prevent any crashes, which most likely are caused by the adapter trying to reference ArrayList elements that are no longer there.
adapter = new TripSelectAdapter(this, thisContext, tripItems);
mTripList.setAdapter(adapter);

Related

How to make expandable cardview childlist in recycle view by reusing the same layout

I want to make view by adding child list on android using cardview in recycleview.
i have made class to store these item and make arraylist on each parent of object if the object have child item, so i can differentiate if the list has child or not.
But i have difficulties to render the same layout to make the child list below the parent list. I am pragmatically make the layout one by one but it will be difficult to make that. So i want to render the same layout to my adapter when i want to make a child list whenever the object/class has arraylist of child list in that object.
this is my adapter right now
public class NotificationListAdapter extends BaseListAdapter<NotificationData, NotificationListAdapter.CustomViewHolder> {
private List<NotificationData> notificationData;
private ArrayList<Integer> indexForHide;
public NotificationListAdapter(Context context) {
super(context);
}
#Override
public void addAll(List<NotificationData> items) {
super.addAll(items);
this.notificationData = items;
}
void setChildNotif(){
ArrayList<NotificationData> childDataItems;
List<NotificationData> notificationDataChild = new ArrayList<NotificationData>();
notificationDataChild.addAll(notificationData);
indexForHide = new ArrayList<Integer>();
for (int i = 0; i < notificationData.size(); i++) {
childDataItems = new ArrayList<>();
if (notificationDataChild.size() == 1) {
notificationData.get(i).setChildNotification(childDataItems);
break;
}
for (int j = i; j < notificationDataChild.size(); j++){
if(i==j){
continue;
}else if (notificationDataChild.size() == 1) {
notificationData.get(i).setChildNotification(childDataItems);
break;
}else{
if(notificationDataChild.get(j).getRfqId()!=0){
if(notificationDataChild.get(j).getRfqId()==notificationData.get(i).getRfqId()){
childDataItems.add(notificationDataChild.get(j));
indexForHide.add(j);
}
}
if(!notificationDataChild.get(j).getInvoiceNumber().equalsIgnoreCase("")) {
if (notificationDataChild.get(j).getInvoiceNumber().equalsIgnoreCase(notificationData.get(i).getInvoiceNumber())) {
childDataItems.add(notificationDataChild.get(j));
indexForHide.add(j);
}
}
}
}
notificationData.get(i).setChildNotification(childDataItems);
Log.d("sizeNotif", i+" :"+notificationData.get(i).getChildNotification().size());
}
Log.d("sizeNotification", " :"+notificationData.size());
Log.d("sizeNotificationDummy", " :"+notificationData.size());
Log.d("isiHideAdapter", Arrays.toString(indexForHide.toArray()));
Log.d("isiHideAdapterSize", indexForHide.size()+"");
}
#Override
protected int getItemResourceLayout(int viewType) {
return R.layout.item_notification_list;
}
int position;
#Override
public int getItemViewType(int position) {
this.position = position;
return position;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
setChildNotif();
return new CustomViewHolder(getView(parent, viewType), onItemClickListener);
}
public class CustomViewHolder extends BaseViewHolder<NotificationData> {
private TextView tvNotifTitle, tvNotifBody, tvNotifStatus, tvNotifTime, tvSignUnread, tvHeaderTitle;
private CardView formContent;
private LinearLayout linearLayout_childItems;
private ImageView expandList;
public CustomViewHolder(View itemView, OnItemClickListener onItemClickListener) {
super(itemView, onItemClickListener);
tvNotifTitle = itemView.findViewById(R.id.tvNotifTitle);
tvNotifBody = itemView.findViewById(R.id.tvNotifBody);
// tvNotifStatus = itemView.findViewById(R.id.tvNotifStatus);
tvNotifTime = itemView.findViewById(R.id.tvNotificationTime);
formContent = itemView.findViewById(R.id.formContent);
tvSignUnread = itemView.findViewById(R.id.tvSignUnread);
tvHeaderTitle = itemView.findViewById(R.id.tvHeaderNotifList);
linearLayout_childItems = itemView.findViewById(R.id.ll_child_items);
expandList = itemView.findViewById(R.id.arrow_expand_notif_list);
//SET CHILD
int intMaxNoOfChild = 0;
for (int index = 0; index < notificationData.size(); index++) {
int intMaxSizeTemp = notificationData.get(index).getChildNotification().size();
if (intMaxSizeTemp > intMaxNoOfChild) intMaxNoOfChild = intMaxSizeTemp;
}
linearLayout_childItems.removeAllViews();
for (int indexView = 0; indexView < intMaxNoOfChild; indexView++) {
TextView textView = new TextView(context);
textView.setId(indexView);
textView.setPadding(20, 20, 0, 20);
textView.setGravity(Gravity.LEFT);
textView.setTextSize(14);
textView.setTextColor(ContextCompat.getColor(context, R.color.colorText));
textView.setBackground(ContextCompat.getDrawable(context, R.drawable.bg_sub_notif_text));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.leftMargin = 16;
textView.setOnClickListener(this);
linearLayout_childItems.addView(textView, layoutParams);
}
}
#Override
public void bind(NotificationData item) {
String title = splitString(item.getTitle());
tvNotifTitle.setText(title);
tvNotifBody.setText(item.getContent());
String txtTime = item.getCreatedAtDisplay().replaceAll("WIB", "");
tvNotifTime.setText(txtTime);
if (position == 0) {
((ViewGroup.MarginLayoutParams) formContent.getLayoutParams()).topMargin = dpToPx(12);
}
((ViewGroup.MarginLayoutParams) formContent.getLayoutParams()).bottomMargin = dpToPx(12);
if (position == getItemCount() - 1) {
((ViewGroup.MarginLayoutParams) formContent.getLayoutParams()).bottomMargin = dpToPx(80);
}
if(item.getIsRead()==1){
formContent.setCardBackgroundColor(context.getResources().getColor(R.color.gray1));
formContent.setCardElevation(5);
formContent.setRadius(15);
tvSignUnread.setVisibility(View.GONE);
}else if(item.getIsRead()==0){
}
//setHeader
Calendar calendar;
SimpleDateFormat dateFormat;
calendar = Calendar.getInstance();
dateFormat = new SimpleDateFormat("yyyy-MM-dd") ;
String date, yesterdayDate, dateDisplayData, dateData;
date = dateFormat.format(calendar.getTime());
calendar.add(Calendar.DATE, -1);
yesterdayDate = dateFormat.format(calendar.getTime());
String[] arrDateDisplayData = item.getCreatedAtDisplay().split(",", 5);
dateDisplayData = arrDateDisplayData[0];
String[] arrDateData = item.getCreatedAt().split(" ", 5);
dateData = arrDateData[0];
Log.d("datenow", date);
Log.d("dateyesterday", yesterdayDate);
Log.d("dateDisplayData", dateDisplayData);
Log.d("dateData", dateData);
if(dateData.equalsIgnoreCase(date)){
tvHeaderTitle.setText("Hari ini");
}else if(dateData.equalsIgnoreCase(yesterdayDate)){
tvHeaderTitle.setText("Kemarin");
}else{
tvHeaderTitle.setText(dateDisplayData);
// tvHeaderTitle.setVisibility(View.GONE);
}
if (getAdapterPosition() > 0) {
String[] timePrev = notificationData.get(getAdapterPosition() - 1).getCreatedAt().split(" ");
if (dateData.equalsIgnoreCase(timePrev[0])) {
tvHeaderTitle.setVisibility(View.GONE);
}
}
if(indexForHide.contains(getAdapterPosition())){
formContent.setVisibility(View.GONE);
}
//SET CHILD
NotificationData dummyParentDataItem = notificationData.get(position);
int noOfChildTextViews = linearLayout_childItems.getChildCount();
for (int index = 0; index < noOfChildTextViews; index++) {
TextView currentTextView = (TextView) linearLayout_childItems.getChildAt(index);
currentTextView.setVisibility(View.VISIBLE);
}
int noOfChild = 0;
if(dummyParentDataItem.getChildNotification()==null){
noOfChild = 0;
}else{
noOfChild = dummyParentDataItem.getChildNotification().size();
}
if (noOfChild < noOfChildTextViews) {
for (int index = noOfChild; index < noOfChildTextViews; index++) {
TextView currentTextView = (TextView) linearLayout_childItems.getChildAt(index);
// currentTextView.setVisibility(View.GONE);
}
}
for (int textViewIndex = 0; textViewIndex < noOfChild; textViewIndex++) {
TextView currentTextView = (TextView) linearLayout_childItems.getChildAt(textViewIndex);
currentTextView.setText(dummyParentDataItem.getChildNotification().get(textViewIndex).getTitle());
/*currentTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, "" + ((TextView) view).getText().toString(), Toast.LENGTH_SHORT).show();
}
});*/
}
if (noOfChild > 0) {
expandList.setVisibility(View.VISIBLE);
expandList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (linearLayout_childItems.getVisibility() == View.VISIBLE) {
linearLayout_childItems.setVisibility(View.GONE);
// Toast.makeText(context, "expand", Toast.LENGTH_SHORT).show();
expandList.setImageResource(R.drawable.ic_arrow_up_blue);
}
else {
linearLayout_childItems.setVisibility(View.VISIBLE);
expandList.setImageResource(R.drawable.ic_arrow_down_blue);
}
}
});
}else {
linearLayout_childItems.setVisibility(View.GONE);
}
}
public int dpToPx(int dp) {
Resources r = context.getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp, r.getDisplayMetrics()
);
return px;
}
public String splitString(String tempString){
StringBuilder finalString = new StringBuilder(tempString);
int i = 0;
while ((i = finalString.indexOf(" ", i + 20)) != -1) {
finalString.replace(i, i + 1, "\n");
}
return finalString.toString();
}
}
}
please help me to render my layout whenever i want to make a child list under my parent list so i can simplify my code above and not making the child layout programatically

Searching and deleting rows in Custom ListView

I'm trying to create a ListView for a Friends list. It has a search functiton in which tthe user can search for a particular freind and then delete them as a friend, message them and so forth.
However, I'm having trouble removing them. I don't think I understand the positioning, or finding out the correct position on where the users freind is in the list.
I want to make sure that in all cases, the user is removed from the correct position. For instance, if the user uses the search function and only one user is returned. Then I don't want the user to be removed at position 0 (one user), I want it to be removed at the correct position so that when the user goes back to the full list. Position 0 in the list isn't accidentaly removed.
Could someone review the code? and show a slight indication as to where I am going wrong with this?
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
res = getResources();
searchField = (EditText) findViewById(R.id.EditText01);
lv = (ListView) findViewById(android.R.id.list);
//button = (Button)findViewById(R.id.btnFriendList);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
//button.setFocusable(false);
list = new ArrayList<Friend>();
nameBlock = res.getStringArray(R.array.names);
descBlock = res.getStringArray(R.array.descriptions);
names = new ArrayList<String>();
for(int i = 0; i < nameBlock.length; i++) {
names.add((String)nameBlock[i]);
}
descr = new ArrayList<String>();
for(int i = 0; i < descBlock.length; i++) {
descr.add((String)descBlock[i]);
}
images = new ArrayList<Integer>();
for(int i = 0; i < imageBlock.length; i++) {
images.add((Integer)imageBlock[i]);
}
//imageBlock = res.getIntArray(R.array.images);
int size = nameBlock.length;
for(int i = 0 ; i < size; i++) {
Log.d("FREINDADD", "Freind Added" + i);
list.add(new Friend(i, names.get(i), descr.get(i), images.get(i)));
//friendList2.add(new Friend(i, names.get(i), descr.get(i), images.get(i)));
}
Log.i("Application", "Application started succesfully...");
adapter = new CustomAdapter(this);
setListAdapter(adapter);
Log.i("VIRTU", "Count" + adapter.getCount());
//adapter.getCount();
searchField.addTextChangedListener(new TextWatcher()
{
#Override public void afterTextChanged(Editable s) {}
#Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override public void onTextChanged(CharSequence s, int start, int before, int count)
{
list.clear();
textlength = searchField.getText().length();
for (int i = 0; i < names.size(); i++)
{
if (textlength <= names.get(i).length())
{
if(names.get(i).toLowerCase().contains(searchField.getText().toString().toLowerCase().trim())) {
Log.i("VirtuFriendList", "List recyling in process... ");
list.add(new Friend(i, names.get(i), descr.get(i), images.get(i)));
}
}
}
AppendList(list);
}
});
}
public void AppendList(ArrayList<Friend> list) {
setListAdapter(new CustomAdapter(this));
}
class CustomAdapter extends BaseAdapter {
private Context context;
public CustomAdapter(Context context) {
this.context = context;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return list.size();
}
class ViewHolder {
TextView userName;
TextView userDesc;
ImageView userImage;
Button userButton;
ViewHolder(View view) {
userImage = (ImageView)view.findViewById(R.id.imageview);
userName = (TextView)view.findViewById(R.id.title);
userDesc = (TextView)view.findViewById(R.id.mutualTitle);
userButton = (Button)view.findViewById(R.id.btn);
}
}
ViewHolder holder;
View row;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
row = convertView;
if(row == null)
{
// If it is visible to the user, deploy the row(s) - allocated in local memory
LayoutInflater inflater = (LayoutInflater)context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.search_list_item, parent, false);
holder = new ViewHolder(row);
row.setTag(holder);
Log.d("VIRTU", "Row deployed...");
}
else
{
// Recycle the row if it is not visible to to the user - store in local memory
holder = (ViewHolder)row.getTag();
Log.d("VIRTU", "Row recycled...");
}
Friend temp = list.get(position);
// Set the resources for each component in the list
holder.userImage.setImageResource(temp.getImage());
holder.userName.setText(temp.getName());
holder.userDesc.setText(temp.getDesc());
((Button)row.findViewById(R.id.btn)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu pop = new PopupMenu(getApplicationContext(), v);
MenuInflater inflater = pop.getMenuInflater();
inflater.inflate(R.menu.firned_popup_action,pop.getMenu());
pop.show();
pop.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
int choice = item.getItemId();
switch(choice) {
case R.id.message:
break;
case R.id.unfollow:
break;
case R.id.unfriend:
int position = (Integer)row.getTag();
list.remove(position);
names.remove(position);
images.remove(position);
descr.remove(position);
adapter = new CustomAdapter(context);
lv.setAdapter(adapter);
adapter.notifyDataSetChanged();
break;
case R.id.cancel:
}
return false;
}
});
}
});
return row;
}
}
}
I think as your structure stands, you will continue to have this problem. My suggestion would be to assign a FriendID (or something similar) to each friend, and when you are building your list, instead of just passing userImage, userName, userDesc and userButton, pass along friendID as well.
For example, I have five friends, and here is their information:
userImage userName userDesc userButton friendID
x Jordyn x x 0
x Sam x x 1
x Connor x x 2
x Paul x x 3
x Raphael x x 4
But my search for (pretending you can search by one letter) those with 'o' in their name returns,
userImage userName userDesc userButton friendID
x Jordyn x x 0
x Connor x x 2
That way, when you delete the 1th row, it actually removes friendID = 2 from your friend list instead of the 1th row from your original friend list, which would've been Sam, which was not your intention.
Hope that helps!
EDIT:
1: add a hidden TextView to your rows called FriendID in your layout file (let me know if you need help with that).
Now, ViewHolder will look like this:
class ViewHolder {
TextView userName;
TextView userDesc;
ImageView userImage;
Button userButton;
TextView friendID;
ViewHolder(View view) {
userImage = (ImageView)view.findViewById(R.id.imageview);
userName = (TextView)view.findViewById(R.id.title);
userDesc = (TextView)view.findViewById(R.id.mutualTitle);
userButton = (Button)view.findViewById(R.id.btn);
friendID = (TextView)view.findViewById(R.id.friendID);
}
}
2: add an arraylist for the friendIDs:
...
descr = new ArrayList<String>();
for(int i = 0; i < descBlock.length; i++) {
descr.add((String)descBlock[i]);
}
images = new ArrayList<Integer>();
for(int i = 0; i < imageBlock.length; i++) {
images.add((Integer)imageBlock[i]);
}
friendIDs = new ArrayList<Integer>();
for(int i = 0; i < friendIDsBlock.length; i++) {
images.add((Integer)friendIdsBlock[i]);
}
...
3: searchField.addTextChangedListener will now look like:
int size = nameBlock.length;
for(int i = 0 ; i < size; i++) {
Log.d("FREINDADD", "Freind Added" + i);
list.add(new Friend(i, names.get(i), descr.get(i), images.get(i)));
//friendList2.add(new Friend(i, names.get(i), descr.get(i), images.get(i), friendIds.get(i)));
}
Log.i("Application", "Application started succesfully...");
4: Now, when you unfriend someone, make sure to get the FriendID at the selected row as opposed to the row index. Then, remove the friend from the search list with the given FriendID as well as the friend from the general friend list with the given FriendID.
You'll have to forgive me, I don't have an IDE in front of me at the moment but I think that about covers it!

getView not returning view parameters

I have an AdapterView that displays a list and headers that separate different list categories. The list is populated by a SQLite database with user input. So far everything is working.
I want to remove the headers when there are no items in the header's category. The code is as follows:
public View getView(int position, View convertView, ViewGroup parent)
{
int viewType = getItemViewType(position);
if (viewType == TYPE_NORMAL)
{
// If the convertView is a textview (group), ignore it
if (convertView instanceof TextView)
{
convertView = null;
}
final int mapCursorPos = getInteralItemPosition(position);
return super.getView(mapCursorPos, convertView, parent);
}
else
{
// Check if it's a text view
TextView text;
if (convertView == null || !(convertView instanceof TextView))
{
((ListView) parent).setDivider(null);
((ListView) parent).setDividerHeight(0);
text = (TextView) inflater.inflate(R.layout.main_list_group, parent, false);
}
else
{
text = (TextView) convertView;
}
final String group = groupsIndexer.get(position).getName(resources);
//Code to hide menu title.
text.setText(group);
text.setVisibility(View.INVISIBLE);
myCursor = getCursor();
initCols(myCursor);
myCursor.moveToFirst();
while (myCursor.isAfterLast() == false)
{
String groupCursor = getGroup(myCursor).getName(resources);
if (groupCursor == group)
{
text.setHeight(12);
text.setPadding(20, 10, 0, 10);
text.setVisibility(View.VISIBLE);
}
myCursor.moveToNext();
}
return text;
}
}
So, as you can see I started by setting the text as invisible and then querying the database to check if there is any item in their specific category and if there is I set the visibility to visible.
However when returning, the method seems to ignore whatever's in the while loop. Is it not possible to format each textview object individually through getView() like this?
Thanks in advance.
Here's something that should put you in the right direction.
import java.util.ArrayList;
import java.util.Collections;
import android.content.Context;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.Paint;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class GroupedListAdapter extends BaseAdapter
{
private static final int TYPE_NORMAL = 0;
private static final int TYPE_GROUP = 1;
private static final int MAX_TYPES = 2;
private final Context mContext;
private final LayoutInflater mInflater;
private final ContactManager mContactManager;
private final ArrayList<GroupItem> mItems = new ArrayList<GroupItem>();
private final DataSetObserver mDataSetObserver = new MyDataSetObserver();
private boolean mDataValid = false;
private Cursor mCursor = null;
private int mIndexId;
private int mIndexSummary;
private int mIndexType;
private int mIndexSender;
private int mIndexReciever;
private int mIndexCompleted;
private int mIndexCompletedBy;
public GroupedListAdapter(Context context)
{
mContext = context;
mContactManager = new ContactManager(context);
mInflater = LayoutInflater.from(context);
}
public void changeCursor(Cursor newCursor)
{
if(newCursor == mCursor){
return;
}
Cursor oldCursor = mCursor;
if(oldCursor != null) {
if(mDataSetObserver != null){
oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
}
mCursor = newCursor;
if(newCursor != null){
if(mDataSetObserver != null){
newCursor.registerDataSetObserver(mDataSetObserver);
}
mIndexId = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns._ID);
mIndexSummary = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns.SUMMARY);
mIndexType = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns.TYPE);
mIndexSender = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns.SENDER);
mIndexReciever = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns.RECIEVER);
mIndexCompleted = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns.COMPLETED);
mIndexCompletedBy = newCursor.getColumnIndexOrThrow(DatabaseContract.Task.Columns.COMPLETED_BY);
// calculate types and index mappings
/*
* 1. Sent (5)
* 2. Item 5
* 3. Item 6
* 4. Received (9)
* 5. Item 9
* 6. Today (1)
* 7. Item 1
* 8. Item 2
* 9. Item 3
*
*/
// allocate
int count = newCursor.getCount();
mItems.ensureCapacity(count);
if(newCursor.moveToFirst()){
int i = 0;
do{
mItems.add(new GroupItem(getGroupId(newCursor), i, TYPE_NORMAL));
i++;
}while(newCursor.moveToNext());
}
Collections.sort(mItems);
int lastGroupId = -1;
for(int i = 0; i < mItems.size(); i++){
final GroupItem item = mItems.get(i);
if(lastGroupId != item.group_id){
mItems.add(i, new GroupItem(item, TYPE_GROUP));
lastGroupId = item.group_id;
}
}
mDataValid = true;
// notify the observers about the new cursor
notifyDataSetChanged();
}
else{
mDataValid = false;
mIndexId = -1;
mIndexSummary = -1;
mIndexType = -1;
mIndexSender = -1;
mIndexReciever = -1;
mIndexCompleted = -1;
mIndexCompletedBy = -1;
mItems.clear();
// notify the observers about the lack of a data set
notifyDataSetInvalidated();
}
if(oldCursor != null) {
oldCursor.close();
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
if(!mDataValid) {
throw new IllegalStateException("this should only be called when the cursor is valid");
}
GroupItem item = mItems.get(position);
if(!mCursor.moveToPosition(item.position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
final View view;
if(convertView == null) {
if(item.type == TYPE_GROUP){
view = mInflater.inflate(R.layout.main_list_group, parent, false);
}
else if(item.type == TYPE_NORMAL){
view = mInflater.inflate(R.layout.main_list_item, parent, false);
}
else{
throw new IllegalStateException("Bad TaskItem type");
}
}
else{
view = convertView;
}
if(item.type == TYPE_GROUP){
TextView textGroup = (TextView)view.findViewById(R.id.task_group);
textGroup.setText(mContext.getString(item.group_id));
}
else if(item.type == TYPE_NORMAL){
TextView textTitle = (TextView)view.findViewById(R.id.task_title);
TextView textDescr = (TextView)view.findViewById(R.id.task_description);
String desc;
String type = mCursor.getString(mIndexType);
if(type.equals(DatabaseContract.Task.TASK_TYPE_OWNER)){
desc = mContext.getString(R.string.desc_example);
}
else if(type.equals(DatabaseContract.Task.TASK_TYPE_RECEV)){
final String sender = mCursor.getString(mIndexSender);
final String name = mContactManager.getContactName(sender);
desc = (name != null) ? name : sender;
}
else{
final String receiver = mCursor.getString(mIndexReciever);
final String name = mContactManager.getContactName(receiver);
desc = (name != null) ? name : receiver;
}
textDescr.setText(desc);
String title = mCursor.getString(mIndexSummary);
textTitle.setText(Character.toUpperCase(title.charAt(0)) + title.substring(1));
if(mCursor.getInt(mIndexCompleted) != 0){
textTitle.setPaintFlags(textTitle.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
else{
textTitle.setPaintFlags(textTitle.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
}
return view;
}
#Override
public Cursor getItem(int position)
{
if(mDataValid && mCursor != null){
mCursor.moveToPosition(mItems.get(position).position);
return mCursor;
}
else{
return null;
}
}
#Override
public long getItemId(int position)
{
if(mDataValid && mCursor != null){
if(mCursor.moveToPosition(mItems.get(position).position)){
return mCursor.getLong(mIndexId);
}
else{
return 0;
}
}
else{
return 0;
}
}
#Override
public int getItemViewType(int position)
{
if(mDataValid && mCursor != null){
return mItems.get(position).type;
}
else{
return IGNORE_ITEM_VIEW_TYPE;
}
}
#Override
public int getViewTypeCount()
{
return MAX_TYPES;
}
#Override
public int getCount()
{
if(mDataValid && mCursor != null){
return mItems.size();
}
else{
return 0;
}
}
public Cursor getCursor()
{
return mCursor;
}
#Override
public boolean hasStableIds()
{
return true;
}
private int getGroupId(Cursor c)
{
if(c.getString(mIndexType).equals(DatabaseContract.Task.TASK_TYPE_SENT)){
return R.string.group_sent;
}
else if(c.getString(mIndexType).equals(DatabaseContract.Task.TASK_TYPE_RECEV)){
return R.string.group_received;
}
else{
long time = c.getLong(mIndexCompletedBy);
long delta = (time - System.currentTimeMillis());
if(delta <= DateUtils.HOUR_IN_MILLIS){
return R.string.group_asap;
}
else if(delta <= DateUtils.DAY_IN_MILLIS){
return R.string.group_today;
}
else if(delta <= (DateUtils.DAY_IN_MILLIS * 2)){
return R.string.group_tomorrow;
}
else if(delta <= DateUtils.WEEK_IN_MILLIS){
return R.string.group_this_week;
}
else if(delta <= (DateUtils.WEEK_IN_MILLIS * 2)){
return R.string.group_next_week;
}
else{
return R.string.group_someday;
}
}
}
private class MyDataSetObserver extends DataSetObserver
{
#Override
public void onChanged()
{
mDataValid = true;
notifyDataSetChanged();
}
#Override
public void onInvalidated()
{
mDataValid = false;
notifyDataSetInvalidated();
}
}
private static class GroupItem implements Comparable<GroupItem>
{
public int group_id;
public int position;
public int type;
public GroupItem(int group_id, int position, int type)
{
this.group_id = group_id;
this.position = position;
this.type = type;
}
public GroupItem(GroupItem item, int type)
{
this.group_id = item.group_id;
this.position = item.position;
this.type = type;
}
#Override
public int compareTo(GroupItem another)
{
return group_id < another.group_id ? -1 : (group_id == another.group_id ? 0 : 1);
}
}
}
Change groupCursor == group to groupCursor.equals(group).
BTW I suggest to load the data in another thread, not in the UI thread and especially not in the getView method, because it can be called LOT of times by the ListView

NullPointer cause in CustomListview

I am developing an application in which i have Implement CustomListview with one icon, raitingbar,checkbox. now everything is display fine but when i have insert one button it getting me nullpointer error.i know that nullpointer error cause in situation of not initialize the control... but i have tried so far and not understand what is the proble over here....
i have take one viewHold for declare all Row item..
package com.AppFavorits;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
class ViewHolder {
public ImageView imgvFavrowiconappicon;
public TextView txvxFavrowiconappname;
public RatingBar ratingBar1;
public CheckBox chkbxFavrowsel;
public Button btnFavrowOpen;
ViewHolder(View base) {
this.ratingBar1=(RatingBar)base.findViewById(R.id.ratingBar1);
this.ratingBar1.setFocusable(false);
this.txvxFavrowiconappname=(TextView)base.findViewById(R.id.txvxFavrowiconappname);
this.imgvFavrowiconappicon=(ImageView)base.findViewById(R.id.imgvFavrowiconappicon);
this.chkbxFavrowsel = (CheckBox)base.findViewById(R.id.chkbxFavrowsel);
this.btnFavrowOpen= (Button)base.findViewWithTag(R.id.btnFavrowOpen);
this.chkbxFavrowsel.setFocusable(false);
}
}
CustomAdapter
class RatingAdapter extends ArrayAdapter<RowModel> implements OnClickListener {
private ArrayList<Model> mlist;
boolean[] checkBoxState;
RatingAdapter(ArrayList<RowModel> list, ArrayList<Model> mlist) {
super(Favorites.this, R.layout.rowfavorites,
R.id.txvxFavrowiconappname, list);
checkBoxState = new boolean[list.size()];
this.mlist = mlist;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View row = super.getView(position, convertView, parent);
holder = (ViewHolder) row.getTag();
if (convertView == null) {
holder = new ViewHolder(row);
row.setTag(holder);
} else {
row = convertView;
((ViewHolder) row.getTag()).chkbxFavrowsel.setTag(mlist
.get(position));
}
RatingBar.OnRatingBarChangeListener l = new RatingBar.OnRatingBarChangeListener() {
public void onRatingChanged(RatingBar ratingBar, float rating,
boolean fromTouch) {
Integer myPosition = (Integer) ratingBar.getTag();
RowModel model = getModel(myPosition);
model.rating = rating;
flFavRate[position] = rating;
// stored listitem rating in array
datasource.open();
datasource.UpdateRating(String.valueOf(rating), String.valueOf(position+1));
datasource.close();
}
};
holder.ratingBar1.setOnRatingBarChangeListener(l);
holder.chkbxFavrowsel
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) holder.chkbxFavrowsel
.getTag();
element.setSelected(buttonView.isChecked());
bSelected[position] = isChecked;
element.setsizeInc(sizeincrement);
// if (holder.chkbxFavrowsel.isChecked() ==
// isChecked) {
boolean bAlreadyfav = false;
String prefixlink = "https://play.google.com/store/apps/details?id=";
ShrdDatasource.open();
ArrayList<Comment> alDSPackagenm = ShrdDatasource.getAllPackage();
ArrayList<Comment> alDSRating = ShrdDatasource.getAllRating();
ArrayList<Comment> alDSID = ShrdDatasource.getID();
Log.i(TAG, "First Package cmp"+ alDSPackagenm);
ShrdDatasource.close();
int i = 0 ;
if (alDSPackagenm != null) {
for (i = 0; i < alDSPackagenm.size(); i++) {
if(alDSPackagenm.get(i).toString().equalsIgnoreCase(prefixlink + alPackagenm.get(position).toString() + "1x2optrue") || alDSPackagenm.get(i).toString().equalsIgnoreCase(prefixlink + alPackagenm.get(position).toString() + "1x2opfalse"))
{
bAlreadyfav = true;
break;
}
}
}
GolbPosition = position;
if (bAlreadyfav == true) {
Log.i(TAG, "Share positionis "+i);
Log.i(TAG, "Current positionis "+position);
Log.i(TAG,"ShrdDatasource Rating" + alDSRating.get(i).toString());
Log.i(TAG,"Favorite Rating" + String.valueOf(flFavRate[GolbPosition]));
if(alDSRating.get(i).toString().equalsIgnoreCase(String.valueOf(flFavRate[GolbPosition])))
{
Toast.makeText(getBaseContext(), " App already in Share list ",
Toast.LENGTH_LONG).show();
}
else
{
//alid
/*GolbPosition = position;
new GETFavTask().execute();*/
//UpdateRating
ShrdDatasource.open();
ShrdDatasource.UpdateRating(String.valueOf(flFavRate[GolbPosition]), alDSID.get(i).toString());
ShrdDatasource.close();
//Update Query fire
}
} else {
//Log.i(TAG, "First Package cmp"+ alDSPackagenm.get(position).toString());
Log.i(TAG, "Second Package cmp"+ alPackagenm.get(position).toString());
GolbPosition = position;
new GETFavTask().execute();
// add item in Database when user get select
}
}
});
RowModel model = getModel(position);
ViewHolder holder = (ViewHolder) row.getTag();
holder.ratingBar1.setTag(new Integer(position));
//holder.btnFavrowOpen.setTag(mlist.get(position));
holder.ratingBar1.setRating(model.rating);
holder.imgvFavrowiconappicon.setImageDrawable(drblAlIcon[position]);
holder.txvxFavrowiconappname.setText(alAppName.get(position)
.toString());
holder.chkbxFavrowsel.setChecked(mlist.get(position).isSelected());
holder.chkbxFavrowsel.setTag(mlist.get(position));
holder.btnFavrowOpen.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// OpenApp(alPackagenm.get(position).toString());
}
});
try
{
if (alAppRating.get(position) == null | alAppRating.get(position).toString().equalsIgnoreCase("null")) {
holder.ratingBar1.setRating(0.0f);
} else {
holder.ratingBar1.setRating(Float.parseFloat(alAppRating
.get(position).toString()));
}
}catch (Exception e) {
e.printStackTrace();
}
//holder.ratingBar1.setRating(Float.parseFloat(alAppRating.get(position).toString()));
return (row);
}
Here you can see the button holder.btnFavrowOpen with onclicklistner i got null pointer at that line very much tied what happen here.... if i am remove button code in adapter it getting work fine...but when i write button code again it getting Error of null pointer
use
base.findViewById
and not
base.findViewWithTag

Issue with checkbox checked

i am use this for setting checkbox in listview i have follow all step as per given tutorial, but there are some critical issue with output, is that when i am select first checkbox and scroll down it will change selected item and automatically appear 3rd.
so i think there are something wrong with getview. so please help me out this ....
here is my code ::
package com.AppFavorits;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.app.ListActivity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.RatingBar;
public class Favorites extends ListActivity {
protected static final String TAG = "Favorites";
CommentsDataSource datasource;
ListView lstFavrowlistv;
ArrayList alAppName;
float[] rate;
boolean[] bSelected;
ArrayList<Comment> alPackagenm;
Drawable[] alIcon;
ViewHolder holder;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
datasource = new CommentsDataSource(this);
datasource.open();
alAppName = datasource.getAllComments();
alPackagenm = datasource.getAllPackage();
Log.i(TAG, "values >>>" + alAppName);
Log.i(TAG, "values >>>" + alPackagenm);
int inc = 0;
alIcon = new Drawable[200];
for (int i = 0; i < alPackagenm.size(); i++) {
Log.i(TAG, "Appname >>>" + GetAllApp.lstpinfo.get(i).pname);
for (int j = 0; j < GetAllApp.lstpinfo.size(); j++) {
if (alPackagenm
.get(i)
.toString()
.equalsIgnoreCase(
GetAllApp.lstpinfo.get(j).pname.toString())) {
alIcon[inc] = GetAllApp.lstpinfo.get(j).icon;
Log.i("TAG", "sqlPackagename"
+ alPackagenm.get(i).toString());
Log.i("TAG", "from getAllapp"
+ GetAllApp.lstpinfo.get(j).pname.toString());
inc++;
}
}
}
ArrayList<RowModel> list = new ArrayList<RowModel>();
ArrayList<Model> Mlist = new ArrayList<Model>();
rate = new float[alAppName.size()];
bSelected = new boolean[alAppName.size()];
Iterator itr = alAppName.iterator();
String strVal = null;
while (itr.hasNext()) {
strVal += itr.next().toString() + ",";
}
int lastIndex = strVal.lastIndexOf(",");
strVal = strVal.substring(0, lastIndex);
System.out.println("Output String is : " + strVal);
String strAr[] = strVal.split(",");
for (int i = 0; i < strAr.length; i++) {
System.out.println("strAr[" + i + "] " + strAr[i]);
}
for (String s : strAr) {
list.add(new RowModel(s));
}
for (String s : strAr) {
Mlist.add(new Model(s));
}
setListAdapter(new RatingAdapter(list, Mlist));
datasource.close();
}
class RowModel {
String label;
float rating = 0.0f;
RowModel(String label) {
this.label = label;
}
public String toString() {
if (rating >= 3.0) {
return (label.toUpperCase());
}
return (label);
}
}
private RowModel getModel(int position) {
return (((RatingAdapter) getListAdapter()).getItem(position));
}
class RatingAdapter extends ArrayAdapter<RowModel> {
private ArrayList<Model> mlist;
RatingAdapter(ArrayList<RowModel> list, ArrayList<Model> mlist) {
super(Favorites.this, R.layout.outbox_list_item,
R.id.txvxFavrowiconappname, list);
this.mlist = mlist;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View row = super.getView(position, convertView, parent);
holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
RatingBar.OnRatingBarChangeListener l = new RatingBar.OnRatingBarChangeListener() {
public void onRatingChanged(RatingBar ratingBar,
float rating, boolean fromTouch) {
Integer myPosition = (Integer) ratingBar.getTag();
RowModel model = getModel(myPosition);
model.rating = rating;
rate[position] = rating;
}
};
holder.chkbxFavrowsel
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(
CompoundButton buttonView, boolean isChecked) {
Model element = (Model) holder.chkbxFavrowsel
.getTag();
element.setSelected(buttonView.isChecked());
bSelected[position] = isChecked;
}
});
holder.chkbxFavrowsel.setTag(mlist.get(position));
holder.ratingBar1.setOnRatingBarChangeListener(l);
} else {
row = convertView;
((ViewHolder) row.getTag()).chkbxFavrowsel.setTag(mlist
.get(position));
}
RowModel model = getModel(position);
ViewHolder holder = (ViewHolder) row.getTag();
holder.ratingBar1.setTag(new Integer(position));
holder.ratingBar1.setRating(model.rating);
holder.imgvFavrowiconappicon.setImageDrawable(alIcon[position]);
holder.txvxFavrowiconappname.setText(alAppName.get(position)
.toString());
holder.chkbxFavrowsel.setChecked(mlist.get(position).isSelected());
return (row);
}
}
}
I really don't understand your code exactly what you are trying to do. I haven't seen before this you are checking holder == null where as it should be convertView == null. If you have a scrolling issue you can check my blog post
holder = (ViewHolder) row.getTag();
if (holder == null) {
holder = new ViewHolder(row);
row.setTag(holder);
...
}
else {
row = convertView;
((ViewHolder) row.getTag()).chkbxFavrowsel.setTag(mlist
.get(position));
}
Use Below Code to your MainActivity.java file.
public class ListViewActivity extends Activity {
ListView mLstView1;
Button mBtn1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mLstView1 = (ListView) findViewById(R.id.mLstView1);
String[] lv_items = { "Dipak", "Rahul", "Hiren", "Nandlal", "Keyur",
"Kapil", "Dipak", "Rahul", "Hiren", "Nandlal", "Keyur",
"Kapil" };
;
mLstView1.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, lv_items));
mLstView1.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mBtn1 = (Button) findViewById(R.id.mBtn1);
mBtn1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// Using a List to hold the IDs, but could use an array.
List<Integer> checkedIDs = new ArrayList<Integer>();
// Get all of the items that have been clicked - either on or
// off
final SparseBooleanArray checkedItems = mLstView1
.getCheckedItemPositions();
for (int i = 0; i < checkedItems.size(); i++) {
// And this tells us the item status at the above position
final boolean isChecked = checkedItems.valueAt(i);
if (isChecked) {
// This tells us the item position we are looking at
final int position = checkedItems.keyAt(i);
// Put the value of the id in our list
checkedIDs.add(position);
System.out.println("Position is:- " + position);
}
}
}
});
}
}

Categories