I have several markers on a google map and in each marker a ListView with several entries.
Each entry can be liked by the user and if he has liked, there is stored an entry in the SQLite Database with the marker ID, the entry ID and if he has liked (1) or took the like back (0) and the activity is reloaded.
Now I want a filled heart to be shown below each List Item the user has liked. The problem is: Especially if there are many entries, there are randomly filled hearts, even if the user only liked one entry. These falsely filled hearts sometimes appear only at scrolling up so I assume, that the ListView does not update its elements at scrolling...
Here is my code:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ListCell cell;
if (convertView == null) {
convertView = inflater.inflate(R.layout.pinboard_list_view_cell, null);
cell = new ListCell();
cell.likes = (TextView) convertView.findViewById(R.id.listViewLikes);
cell.note = (TextView) convertView.findViewById(R.id.listViewNote);
cell.img = (ImageView) convertView.findViewById(R.id.listViewImg);
cell.likeImage = (ImageView) convertView.findViewById(R.id.heartImage);
convertView.setTag(cell);
}
else {
cell = (ListCell)convertView.getTag();
}
cell.position = position;
//Listen-Items mit entsprechenden Elementen aus dem heruntergeladenen Array befüllen
try {
JSONObject jsonObject = this.dataArray.getJSONObject(position);
cell.likes.setText(jsonObject.getString("likes"));
cell.note.setText(jsonObject.getString("note"));
cell.entryID = jsonObject.getString("id");
String img = jsonObject.getString("image");
String urlForImageInServer = baseUrlForImage + img;
Picasso.with(context)
.load(urlForImageInServer)
.placeholder(R.drawable.progress_animation)
.error(R.drawable.no_picture)
.into(cell.img);
objectID = ""+cell.entryID;
dbh = new DbHelper(context);
cursor = getLikes(dbh);
cursor.moveToFirst();
if (cursor.moveToFirst()) {
do {
if (Integer.parseInt(cursor.getString(2)) == 1) {
cell.likeImage.setImageResource(R.drawable.heart_filled);
}
else {
cell.likeImage.setImageResource(R.drawable.heart);
}
}
while(cursor.moveToNext());
}
else {
cursor.close();
}
cursor.close();
}
catch (JSONException e) {
e.printStackTrace();
}
return convertView;
}
public static class ListCell {
private TextView likes;
private TextView note;
private ImageView img;
public ImageView likeImage;
public int position;
public String entryID;
}
public Cursor getLikes(DbHelper dbh) {
dbase = dbh.getReadableDatabase();
String columns[] = {dbh.LIKES_MARKERID, dbh.LIKES_ENTRYID, dbh.LIKES_LIKE};
String selection = dbh.LIKES_MARKERID + " LIKE ? AND " + dbh.LIKES_ENTRYID + " LIKE ? ";
String args[] = {markerID.toString(), objectID};
Cursor cursor = dbase.query(dbh.TABLE_LIKES, columns, selection, args , null, null, null, null);
return cursor;
}
if there are no likes make sure you set disable heart image explictly. Right now it seems you are trying to set it inside do while loop, if flow doesn't goes inside this loop, recycled view will be used which may or may not have disabled heart.
Related
Ok this is annoying but I've been at it for long now.
The button is not updating the values
This is the cursor adapter class, I know it's a lot of code, but you need to look only at the bind view after I have declared the button. I gave the entire code in case it helps someone else implement other things -
`public class FruitsFragmentCursorAdapter extends CursorAdapter {
public FruitsFragmentCursorAdapter(Context context, Cursor cursor) {
super(context,cursor,0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.fragment_fruits,parent,false);
}
#Override
public void bindView(View view, final Context context, final Cursor cursor) {
//final
//First find all the views that I want to modify individually
ImageView imageView = (ImageView) view.findViewById(R.id.fruit_fragment_fruit_image);
TextView engTextView = (TextView) view.findViewById(R.id.fruit_fragment_english_name);
TextView hindiTextView = (TextView) view.findViewById(R.id.fruit_fragment_hindi_name);
TextView measureTextView = (TextView) view.findViewById(R.id.fruit_fragment_unit_measure);
TextView priceTextView = (TextView) view.findViewById(R.id.fruit_fragment_unit_price);
final TextView quantityTextView = (TextView) view.findViewById(R.id.fruit_fragment_quantity_text_view);
TextView priceCalTextView = (TextView) view.findViewById(R.id.fruit_fragment_price_calculation);
//Find the columns of the attributes we are interested in
int columnImage = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_IMAGE);
int columnEngName = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_ITEM_NAME_ENGLISH);
int columnHinName = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_ITEM_NAME_HINDI);
int columnMeasure = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_MEASURE);
int columnPrice = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_UNIT_PRICE);
final int columnQuantity = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_QUANTITY);
final int columnItemSoldID = cursor.getColumnIndex(itemsSoldContractEntry.COLUMN_ITEM_ID);
final int columnID = cursor.getColumnIndex(itemsSoldContractEntry._ID);
//Read the attributes from the cursor
final String image = cursor.getString(columnImage);
final String engName = cursor.getString(columnEngName);
String hinName = cursor.getString(columnHinName);
String measure = cursor.getString(columnMeasure);
String price = cursor.getString(columnPrice);
String quantity = cursor.getString(columnQuantity);
//get the string for the cal text view separately
String calculation = quantity + " x "+price + " = " + Integer.parseInt(quantity)*Integer.parseInt(price);
//Decode the string to create a bitmap
byte[] decodedString = Base64.decode(image,Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString,0,decodedString.length);
//Update the text views with the values
imageView.setImageBitmap(decodedByte);
engTextView.setText(engName);
hindiTextView.setText(hinName);
measureTextView.setText("per "+measure);
priceTextView.setText("₹ " + price);
quantityTextView.setText(quantity);
priceCalTextView.setText(calculation);
//Define the two buttons (increment and decrement)
Button incrementsButton = (Button) view.findViewById(R.id.fruit_fragment_increment);
//Get the position of the cursor
final int position = cursor.getPosition();
//Set the onclick listener
incrementsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Set up a content values object to hold the quantity when updated
ContentValues incrementValue = new ContentValues();
//Move the cursor to the position of the current item under operation
cursor.moveToPosition(position);
//Update the quantity value
int oldQuantity = (cursor.getInt(columnQuantity));
int newQuantity = oldQuantity +1;
//Works till here
//Put the value in the content values
incrementValue.put(itemsSoldContractEntry.COLUMN_QUANTITY,newQuantity);
//Selection claus which will point to the item_sold_id which will be updated
String selection = itemsSoldContractEntry._ID + "=?";
//Get the item id which should be updated
int item_id = cursor.getInt(columnID);
String itemIDArgs = Integer.toString(item_id);
//Works till here
//Selection args claus
String[] selectionArgs = {itemIDArgs};
//Update the value
int something = context.getContentResolver().update(itemsSoldContractEntry.CONTENT_URI_ITEMS_SOLD,incrementValue,selection,selectionArgs);
Log.v("Updated"," Row"+ something);
//This is a toast to check if the correct item is being clicked
Toast.makeText(context,something+"",Toast.LENGTH_SHORT).show();
//New quantity
String newQu = cursor.getString(columnQuantity);
quantityTextView.setText(newQu);
}
});
}
}
Everytime I click on the button, it doesn't update. I don't know why. I have gone through all docs of google and scoured stackoverflow. Still no clue. It returns 0 all the time.
In the comments I have added till what part it works. Please help.
Figured it out. If you notice I use a URI to access the database. I realized the URI was not configured to handle the update and hence was returning 0(the number of rows updated). Once that was fixed it was pretty simple.
Attaching the code with the fix -
//Move the cursor to the position of the current item under operation
cursor.moveToPosition(position);
//Update the quantity value
int oldQuantity = (cursor.getInt(columnQuantity));
int newQuantity = oldQuantity +1;
//Works till here
//Put the value in the content values
incrementValue.put(itemsSoldContractEntry.COLUMN_QUANTITY,newQuantity);
//Selection claus which will point to the item_sold_id which will be updated
String selection = itemsSoldContractEntry._ID + "=?";
//Get the item id which should be updated
int item_id = cursor.getInt(columnID);
String itemIDArgs = Integer.toString(item_id);
//This is a toast to check if the correct item is being clicked
Toast.makeText(context,itemIDArgs+"",Toast.LENGTH_SHORT).show();
//Works till here
//Selection args claus
String[] selectionArgs = {itemIDArgs};
//Update the value
int something = context.getContentResolver().update(
Uri.withAppendedPath(itemsSoldContractEntry.CONTENT_URI_ITEMS_SOLD,Integer.toString(item_id)),
incrementValue,
selection,selectionArgs);
Note - My content provider has a functionality of just writing to one row instead of the entire table and hence if you notice I have appended the id at the end of the URI in the code where I update the quantity.
I am trying to display the contents of my mysqlite database into a listview,
I am able to get the contents and display them in a textview, but for some
reason I can't add the details to an arraylist ? I am not too sure what am doing
wrong. I have looked for multiple solutions but none of them seem to work, am getting an error
Android.database.CursorIndexOutOfBoundsExecption: Index requested -1
Here is what I currently have:
OnCreate:
ArrayAdapter<Contact> currentContactsAdapter = new ContactArrayAdapter();
ListView lvcontacts = (ListView) findViewById(R.id.lvContacts);
lvcontacts.setAdapter(currentContactsAdapter);
tdb = new TestDBOpenHelper(this, "contact.db", null, 1);
sdb = tdb.getWritableDatabase();
new MyContacts().execute();
ListView Adapter:
private class ContactArrayAdapter extends ArrayAdapter<Contact>{
public ContactArrayAdapter(){
super(MainActivity.this, R.layout.listviewitem, addedContacts);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
if(itemView == null){
itemView = getLayoutInflater().inflate(R.layout.listviewitem, parent, false);
}
Contact currentContact = addedContacts.get(position);
TextView name = (TextView) itemView.findViewById(R.id.tvNameitem);
name.setText(currentContact.getName());
TextView phone = (TextView) itemView.findViewById(R.id.tvPhoneitem);
phone.setText(currentContact.getPhone());
TextView email = (TextView) itemView.findViewById(R.id.tvEmailitem);
email.setText(currentContact.getEmail());
return itemView;
}
}
GetContacts:
class MyContacts extends AsyncTask<String, String, String> {
List<Contact> retrievedContacts = new ArrayList<Contact>();
protected String doInBackground(String... args) {
String cname;
String cphone;
String cemail;
// name of the table to query
String table_name = "contact";
// the columns that we wish to retrieve from the tables
String[] columns = {"FIRST_NAME", "PHONE", "EMAIL"};
// where clause of the query. DO NOT WRITE WHERE IN THIS
String where = null;
// arguments to provide to the where clause
String where_args[] = null;
// group by clause of the query. DO NOT WRITE GROUP BY IN THIS
String group_by = null;
// having clause of the query. DO NOT WRITE HAVING IN THIS
String having = null;
// order by clause of the query. DO NOT WRITE ORDER BY IN THIS
String order_by = null;
// run the query. this will give us a cursor into the database
// that will enable us to change the table row that we are working with
Cursor c = sdb.query(table_name, columns, where, where_args, group_by,
having, order_by);
for(int i = 0; i < c.getCount(); i++) {
cname = c.getString(c.getColumnIndex("FIRST_NAME"));
cphone = c.getString(c.getColumnIndex("PHONE"));
cemail = c.getString(c.getColumnIndex("EMAIL"));
c.moveToNext();
retrievedContacts.add(new Contact(cname,cphone,cemail));
}
return null;
}
//Update Contact list when response from server is received
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
for(Contact contact: retrievedContacts)
addedContacts.add(contact);
}
}
It seems that your table "contact" doesn't have the exact structure you are trying to read.
Android.database.CursorIndexOutOfBoundsExecption: Index requested -1
This means that one of these column names is not part of it.
c.getColumnIndex("FIRST_NAME")
c.getColumnIndex("PHONE")
c.getColumnIndex("EMAIL")
So one of them return -1 instead of the index because they not exist in the table.
EDIT:
Then the for loop may be faulty. I suggest to use something like:
if (c != null ) {
if (c.moveToFirst()) { // Always move at the first item
do {
cname = c.getString(c.getColumnIndex("FIRST_NAME"));
cphone = c.getString(c.getColumnIndex("PHONE"));
cemail = c.getString(c.getColumnIndex("EMAIL"));
retrievedContacts.add(new Contact(cname, cphone, cemail));
} while (c.moveToNext());
}
}
c.close(); // always close when done!
Application need to read the phonebook contacts and show it to the user, have more than 8000 contacts on the phone.
Problem is it stuck for very long time while rendering all contacts on the screen.
Please suggest best way to accomplish this task. thanks
Main Method:
Cursor contactsCursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
LogUtils.d("### cursorCount" + contactsCursor.getCount());
contacts = new ArrayList<ImportContactModel>();
importContactList = new ArrayList<ImportContactModel>();
showProgressDialog();
asyncLoader = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
fetchContacts();
return null;
}
protected void onPostExecute(Void result) {
// create an array of Strings, that will be put to our
// ListActivity
adapter = new ImportContactArrayAdapter(
ImportContactSelection.this, contacts);
contactList.setAdapter(adapter);
contactList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
initSearch();
dismissProgressDialog();
};
}.execute();
Class to get Data:
public void fetchContacts() {
String phoneNumber = null;
String email = null;
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
String PROFILE_PIC = ContactsContract.CommonDataKinds.Phone.PHOTO_URI;
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
Uri EMAIL_CONTENT_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
String EMAIL_CONTACT_ID = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
String EMAIL = ContactsContract.CommonDataKinds.Email.DATA;
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(CONTENT_URI, null, null, null,
null);
// Loop for every contact in the phone
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
ImportContactModel tempContact = new ImportContactModel();
String contact_id = cursor
.getString(cursor.getColumnIndex(_ID));
String name = cursor.getString(cursor
.getColumnIndex(DISPLAY_NAME));
String image_uri = cursor.getString(cursor
.getColumnIndex(PROFILE_PIC));
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor
.getColumnIndex(HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
tempContact.setId(contact_id);
if (image_uri != null)
tempContact.setProfilePic(cursor.getString(cursor
.getColumnIndex(PROFILE_PIC)));
else
tempContact.setProfilePic("");
tempContact.setContactName(name);
// Query and loop for every phone number of the contact
Cursor phoneCursor = contentResolver.query(
PhoneCONTENT_URI, null, Phone_CONTACT_ID + " = ?",
new String[] { contact_id }, null);
// Get All Phone Numbers
while (phoneCursor.moveToNext()) {
phoneNumber = phoneCursor.getString(phoneCursor
.getColumnIndex(NUMBER));
tempContact.setContactNo(phoneNumber);
break;
}
phoneCursor.close();
Cursor emailCursor = contentResolver.query(
EMAIL_CONTENT_URI, null, EMAIL_CONTACT_ID + "=?",
new String[] { contact_id }, null);
while (emailCursor.moveToNext()) {
String contactId = emailCursor.getString(emailCursor
.getColumnIndex(EMAIL_CONTACT_ID));
email = emailCursor.getString(emailCursor
.getColumnIndex(EMAIL));
tempContact.setEmail(email);
break;
}
emailCursor.close();
contacts.add(tempContact);
}
}
}
}
Adapter Class
public class ImportContactArrayAdapter extends ArrayAdapter<ImportContactModel> {
private final List<ImportContactModel> list;
private final Activity context;
private ImageLoader mImageLoader;
public ImportContactArrayAdapter(Activity context, List<ImportContactModel> list) {
super(context, R.layout.item_task_contact_select, list);
this.context = context;
this.list = list;
this.mImageLoader = ImageLoader.getInstance();
}
static class ViewHolder {
protected ImageView profilePic;
protected TextView contactName;
protected TextView contactNo;
protected CheckBox checkbox;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.item_task_contact_select, null);
final ViewHolder viewHolder = new ViewHolder();
//viewHolder.profilePic = (ImageView) view.findViewById(R.id.img_import_profilePic);
viewHolder.contactName = (TextView) view.findViewById(R.id.name_text);
viewHolder.contactNo = (TextView)view.findViewById(R.id.tag_text_1);
viewHolder.contactNo.setVisibility(View.VISIBLE);
viewHolder.contactNo.setTextSize(11);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.select_checkbox);
viewHolder.checkbox.setClickable(true);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
ImportContactModel element = (ImportContactModel) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
ImageView avatar = (ImageView) view.findViewById(R.id.img_avatar);
ImageView avatarBorder = (ImageView) view.findViewById(R.id.img_avatar_overlay);
ProgressBar avatarProgress = (ProgressBar) view.findViewById(R.id.img_avatar_progress);
if(!list.get(position).equals(""))
//holder.profilePic.setImageURI(Uri.parse(list.get(position).getProfilePic()));
mImageLoader.displayImage(list.get(position).getProfilePic(), avatar, new AvatarsImageLoadingListener(avatarProgress, avatarBorder, R.drawable.bg_nophoto));
holder.contactName.setText(list.get(position).getContactName());
holder.contactNo.setText(list.get(position).getContactNo());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
}
public ArrayList<ImportContactModel> getCheckList(){
ArrayList<ImportContactModel> tempList = new ArrayList<ImportContactModel>();
for(int i=0;i<list.size();i++){
if(list.get(i).isSelected()){
tempList.add(list.get(i));
LogUtils.d(""+list.get(i).getContactName());
}
}
return tempList;
}
}
So it just shows Loading screen for huge amount of time..
You don't have to fetch all contacts to display them. AsyncTask has publishProgress method. I'm not experienced with Cursor class, since I prefer ORM for that, so I'll write in pseudo code, you'll have to adapt it yourself.
//in AsyncTask
protected Void doInBackground(params){
while(cursor.moveToNext()){
contactInfo = createContact(currentCursorValue);
publishProgress(contactInfo);
}
}
onProgressUpdate(contactInfo){
if(adapter==null){
//first time adapter setup
}
adapter.add(contactInfo);
adapter.notifyDataSetChanged();
}
This way, every time you pull a record from Db, you publish it, and items are added continuously. User won't notice any delay, unless he tries searching for not yet existing items, or you want to implement that big pop up letter for fast scroll. Still, above code is not very effective, since publishing the progress every .001 second or so, is not very smart, so you can either publish every 20 results, or publish them every second, up to you.
I've converted a list project from a BaseAdapter to an ArrayAdapter ListActivity because I was told in another question that ArrayAdapter was more dynamic and better at, specifically, allowing an item to be removed from the list and then updating to reflect that removal. I'm still running into the same issue with my ArrayAdapter, though, as follows:
I get my list data as so:
public void loadAdapter(){
DatabaseHelper helper = new DatabaseHelper(ActivityMain.this);
database = helper.getReadableDatabase();
Cursor data = database.query("list_data", fields, null, null, null,
null, null);
Integer tindex = data.getColumnIndex("listTitle");
Integer iindex = data.getColumnIndex("listType");
itemCount = 0;
for (data.moveToFirst(); !data.isAfterLast(); data.moveToNext()) {
m_parts.add(new Item(data.getString(tindex), data.getString(iindex)));
itemCount++;
}
data.close();
for (int j = 0; j < 10; j++) {
m_parts.add(new Item("", "R"));
}
m_adapter = new ItemAdapter(ActivityMain.this, R.layout.listview, m_parts);
setListAdapter(m_adapter);
}
with this custom adapter:
public class ItemAdapter extends ArrayAdapter<Item> {
private ArrayList<Item> objects;
public ItemAdapter(Context context, int textViewResourceId,
ArrayList<Item> objects) {
super(context, textViewResourceId, objects);
this.objects = objects;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview, null);
}
Item i = objects.get(position);
if (i != null) {
TextView textview = (TextView) v.findViewById(R.id.tv_main);
ImageView imageview = (ImageView) v.findViewById(R.id.iv_main);
TextView textview2 = (TextView) v.findViewById(R.id.tv_main2);
textview.setText(i.getText());
textview2.setText(i.getText());
imageview.setScaleType(ScaleType.FIT_XY);
Integer theDrawable;
if (i.getImage() != "L") {
theDrawable = R.drawable.listview_regular;
} else {
theDrawable = R.drawable.listview_location;
}
imageview.setImageResource(theDrawable);
}
v.setOnClickListener(new OnItemClickListener(position));
v.setOnLongClickListener(new OnItemLongClickListener(position));
return v;
}
}
The context menu from longclicklistener offers a delete option, which uses this
private void showDialogOnLongClick(final int position) {
Builder alert = new AlertDialog.Builder(this);
ArrayList<String> listInfo = getListInfo(position);
String content = listInfo.get(1);
String numItems = "";
if (content != null && content.indexOf("|~|") > -1) {
String[] contentSplit = content.split("\\|\\~\\|");
numItems = contentSplit.length + " items in list";
} else {
numItems = "No items in list";
}
String listTitle = listInfo.get(0);
String created = "Created: " + listInfo.get(2);
String modified = "Modified: " + listInfo.get(3);
String delete = "Delete";
String edit = "Edit";
final String[] items = new String[] { created, modified, numItems,
delete, edit };
alert.setTitle(listTitle);
alert.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 3:
if (deleteList(position)) {
//listview.invalidate();
//Item itemToRemove = m_parts.remove(position);
//m_adapter.remove(itemToRemove);
//m_adapter.remove(toRemove);
//m_adapter.notifyDataSetInvalidated(); <-- These are all things I've tried
//m_adapter.clear(); in various combinations
//m_adapter.remove(position);
Item toRemove = m_adapter.getItem(position);
m_parts.remove(toRemove); //or, m_parts.remove(position);<-This is what should work
m_adapter.notifyDataSetChanged();
loadAdapter();
// runOnUiThread(new Runnable() {
// public void run() {
// m_adapter.notifyDataSetChanged(); <--I've tried a thread approach
// }
// });
}
break;
case 4:
Intent i = new Intent(ActivityMain.this,
ShowARegularList.class);
i.putExtra("list_id", (position + 1) + "");
startActivity(i);
break;
}
}
});
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.show();
}
which, in case 3 changes the database with
// Delete single list item data
public boolean deleteList(int id) {
id++;
DatabaseHelper helper = new DatabaseHelper(this);
database = helper.getWritableDatabase();
// ContentValues values = new ContentValues();
// values.put("_id", id);
database.delete("list_data", "_id =" + id, null);
database.close();
// text = text.removeElementStr();
// itemCount--;
return true;
}
The above works to remove an item from the list, and closes the gap visually. But, when clicking on the "old" spot from which the item was removed (which raises a new intent to edit the selected item), an exception is raised in the new activity on querying the db (last line, 97 in logcat):
final Integer thisListID = Integer.parseInt(listIDstr);
final DatabaseHelper helper = new DatabaseHelper(this);
database = helper.getReadableDatabase();
Cursor cursor = database.query("list_data", new String[] { "listTitle",
"listContent", "dateCreated", "dateModified" }, "_id = " + thisListID
+ "", null, null, null, null);
ArrayList<String> listInfo = new ArrayList<String>();
if (cursor != null && cursor.moveToFirst()) {
listInfo.add(cursor.getString(cursor.getColumnIndex("listTitle")));
listInfo.add(cursor.getString(cursor.getColumnIndex("listContent")));
listInfo.add(cursor.getString(cursor.getColumnIndex("dateCreated")));
listInfo.add(cursor.getString(cursor.getColumnIndex("dateModified")));
}
cursor.close();
strListContent = listInfo.get(1).trim();
with logcat
java.lang.RuntimeException: Unable to start activity...
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2049)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2083)
at android.app.ActivityThread.access$600(ActivityThread.java:134)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1233)
...
at com.baked.listanywhere.ShowARegularList.onCreate(ShowARegularList.java:97)
The list items with index less than the deleted one are fine; those with greater index are one off in their contents. I suspect an error in logic on my part in the query, querying an index that is no longer there...but it seems I should be able to redraw the list and have an index list that mirrors the database. What I would truly like to do is extinguish any memory of the list and then refill it, but I can't seem to do this...any help would be much appreciated!
Well, as no one is chiming in, I've resolved the issue by querying
Cursor cursor = database.rawQuery("SELECT * FROM list_data ORDER BY _id LIMIT 1 OFFSET '"+ thisListID +"'", null);
thanks to Wojtek at this question. And, yes,
case 3:
if (deleteList(position)) {
Item toRemove = m_adapter.getItem(position);
m_parts.remove(toRemove);
m_adapter.notifyDataSetInvalidated();
loadAdapter();
break;
}
was working fine, even though I could have sworn that was the issue!
So I have a ListView on which I click to start new Activity called MerchantView.
Between the activities I am passing the uid which is a unique identifier of a merchant.
Im then extracting merchant data from DB and want to view this data in this view.
Everything works (while debugging i can see that data is taken from DB and passed properly to setText methods) but the data does not show, am I doing this right?
public class MerchantView extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.merchant);
String desc = "";
String name = "";
Bundle extras = getIntent().getExtras();
String uid = "0";
if(extras !=null) {
uid = extras.getString("uid");
}
// get merchant from database
if(Integer.valueOf(uid) > 0){
Cursor c = Utilities.db.query(mydb.TABLE_MERCHANT,
null,
"uid=?", new String[] {uid}, null, null, null);
if(c.moveToFirst() != false){
name = c.getString(c.getColumnIndex(MerchantsColumns.COLname));
desc = c.getString(c.getColumnIndex(MerchantsColumns.COLdesc));
}
// set values to UI
TextView descUI = (TextView) findViewById(R.id.merchantDescription);
descUI.setText(desc);
TextView nameUI = (TextView) findViewById(R.id.merchantName);
nameUI.setText(name);
}
else{
}
Button buttonMerchants = (Button) findViewById(R.id.buttonMerchants);
buttonMerchants.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}
});
}
}
Data was set properly. The problem was in layout. The header (LinearLayout) at the top had two buttons and it was set to android:layout_height="fill_parent" which was taking whole space. After fixing that, data is showing properly.
Try Below code hope it helps
SQLiteDatabase myDB = this.openOrCreateDatabase("databasename.db", SQLiteDatabase.OPEN_READWRITE, null);
try{
Cursor c = myDB.rawQuery("select name, desc from abctable where uid="+uid, null);
int Column1 = c.getColumnIndex("name");
int Column2 = c.getColumnIndex("desc");
// Check if our result was valid.
c.moveToFirst();
if (c != null) {
int i = 0;
// Loop through all Results
do {
i++;
String name = c.getString(Column1);
String desc = c.getString(Column2);
TextView descUI = (TextView) findViewById(R.id.merchantDescription);
descUI.setText(desc);
TextView nameUI = (TextView) findViewById(R.id.merchantName);
nameUI.setText(name);
} while (c.moveToNext());
}
} catch (SQLiteException e) {
e.printStackTrace();
} finally {
if (myDB != null)
myDB.close();
}