SQLite row IDs do not match the ListView row IDs - android

I have an SQLite database and a ListView displaying in the main activity. In the ListView, I display the details of each list number and upon pressing the list item, a new activity opens up which displays the details in a TextView.
I have a delete function for each of these ListViews and they are not working properly. Essentially, a unique ID is given to each created ListView, which is how the SQLite databases should work. However, upon deleting a row within the ListView, the unique ID increases but the row ID deletes that number and moves everything up. This means that after you delete an item, the row IDs and the database IDs no longer match up and when trying to select an item within the ListView, it crashes. This is an extract from my database adapter class:
public Integer deleteStat(Integer id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(STATS_TABLE, "id = ? ", new String[]{Integer.toString(id)});
}
This is my first attempt in the main activity. I got some information from this post but a failed to get the correct integer and received syntax errors:
obj.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
TextView pos = (TextView) findViewById(R.id.editTitle);
displayText(Integer.parseInt(pos.getText().toString()));
}
});
}
public void displayText(int pos)
{
pos++;
String s = "";
s += pos;
Intent intent = new Intent(getApplicationContext(), DisplayStatsActivity.class);
intent.putExtra("id", s);
startActivity(intent);
}
This is my second attempt in the main activity. I used this tutorial to help me. The code I used from that website ruined the entire delete functionality:
obj.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
int id_To_Search = arg2 + 1;
int id_To_Search = arg0.getCount() - arg2;
Bundle dataBundle = new Bundle();
dataBundle.putInt("id", id_To_Search);
Intent intent = new Intent(getApplicationContext(), DisplayStatsActivity.class);
intent.putExtras(dataBundle);
startActivity(intent);
How do I get the database IDs to match up with the row IDs? Any suggestions on how to do that?
EDIT: Added in Hashmap Code. When I press on a ListView Item, nothing happens
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mydb = new StatisticsDbAdapter(this);
ArrayList array_list = mydb.getAllStats();
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, array_list);
obj = (ListView) findViewById(R.id.listView1);
obj.setAdapter(arrayAdapter);
/*
New code starts here
*/
Bundle extras = getIntent().getExtras();
if (extras != null) {
int Value = extras.getInt("id");
if (Value > 0) {
//means this is the view part not the add contact part
Cursor cursor = mydb.getData(Value);
hashMap.put(cursor.getString(1), cursor.getInt(0));
obj.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int arg2, long arg3) {
TextView textView = (TextView) view.findViewById(R.id.editTitle);
Bundle dataBundle = new Bundle();
dataBundle.putInt("id", hashMap.get(textView.getText().toString()));
Intent intent = new Intent(getApplicationContext(), DisplayStatsActivity.class);
intent.putExtras(dataBundle);
startActivity(intent);
}
});
}
}
}

You should never pass a ListView position to delete a row in a database. I have done that many times before. First of all, within the class you are managing the click events, create a new HashMap. This HashMap will be used to store our row IDs from the database and we'll refer to that rather than the ListView item position. To create it, type this code:
public HashMap<String, Integer> hashMap = new HashMap<>();
Once you have done that, in the function where you display all of the rows in the ListView, you must also load up the same items into the HashMap like this:
hashMap.put(cursor.getString(1), cursor.getInt(0));
Please note that cursor.getString(1) might not be what you used. Please replace the 1 with your appropriate column number that has the name stored within it. cursor.getInt(0) gets the row ID from the database and the column number might be different for you, too. Now, within our OnClickListener function, we can type:
obj.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view) {
TextView textView = (TextView) view.findViewById(R.id.editTitle);
Bundle bundle = new Bundle();
bundle.putInt("id", hashMap.get(textView.getText().toString()));
Intent intent = new Intent(getApplicationContext(), DisplayStatsActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
Please note that the hashMap variable needs to be within the same class where you manage the click events of your ListView or you will get mistakes. Some of the parametres that you originally passed were removed since you don't need them. Also, I found this to work much better using a RecyclerView but that's now up to you. If you're having problems, please don't hesitate to comment below and I'll try to answer as soon as possible.

Related

ToggleButtons on ListView

What is the syntax to get a specific togglebutton from a listview containing the said togglebuttons within a listview_row layout?
I would like to initiate the state of each togglebutton (based on some values originating from a Database), within the onCreate method. I have the following code within a loop, but I am not sure how to change it to reference a specific togglebutton from the listview.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mydb = new DBHelper(this);
ArrayList array_list = mydb.getAllAlarms();
for(int i = 0; i < array_list.size(); i++) {
arrayListItem = array_list.get(i).toString();
activationInt = Integer.parseInt(arrayListItem);
LayoutInflater vi = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.listview_row, null);
alarm_activated = (ToggleButton) view.findViewById(R.id.alarm_activated);
if (activationInt == 1) {
alarm_activated.setChecked(true);
alarm_activated.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.MULTIPLY);
} else {
alarm_activated.setChecked(false);
}
}
ArrayAdapter arrayAdapter =
new ArrayAdapter(this, listview_row,R.id.alarm_name,array_list);
obj = (ListView)findViewById(R.id.listViewAlarms);
obj.setAdapter(arrayAdapter);
obj.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
String itemVal =(String) arg0.getItemAtPosition(arg2);
Bundle dataBundle = new Bundle();
dataBundle.putString("name", itemVal);
Intent intent = new
Intent(getApplicationContext(),DisplayAlarm.class);
intent.putExtras(dataBundle);
startActivity(intent);
}
});
Updating views of a ListView/RecyclerView should not really be done in this way.
First because child views referenced in a ListView do not represent the totality of your rows, but only the visible rows at one moment.
ListView binds their item views on DataSet values, so you'd better use data objects that contains your "checked" boolean status, then when you need to sync, update your DataSet and notifyDataSetChange your adapter.
So you'll have to create your custom adapter by following this kind of example : Custom Adapter for List View

App is passing wrong text from list items textview

My app is passing text taken from TextView in list item. I know that text in this text views is right cause I can see that it's ok. Text taken from TextView is pid of photo in MySql database.
My onItemClick code :
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (((ImageView) findViewById(R.id.reviewImageView)).getBackground() != null) {
String pid = ((TextView) findViewById(R.id.reviewListPid)).getText().toString();
Intent i = new Intent(getApplicationContext(), photoActivity.class);
i.putExtra("pid", pid);
i.putExtra("database", database_name);
startActivity(i);
}
}
});
I'm sure that text in every list item is right and I can see that text passed to next activity is wrong, cause I can see variable value in log and it's wrong.
Two things:
This won't fix your issue but instead of using getApplicationContext() in your Intent intialization use <YourActivityName>.this instead.
The way you are getting your String is a little unusual, and unnecessary. Most likely, you are loading your adapter for your listview with some sort of array that contains the "pid", correct? So then just get the value from that array in your onItemClickListener callback.
It would look like this:
String[] items = {"..."};
ArrayAdapter<String> itemsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
listView.setAdapter(itemsAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (((ImageView) findViewById(R.id.reviewImageView)).getBackground() != null) {
String pid = items[position];
Intent i = new Intent(MyActivity.this, photoActivity.class);
i.putExtra("pid", pid);
i.putExtra("database", database_name);
startActivity(i);
}
}
});

How do I replace an item in a listview?

I have a listview which is populated by an array adpater. A user starts on activity a and after clicking an item in the listview is taken to activity b where they can edit the item they clicked. The edited item from B is sent back to A through an intent after the user returns to A. I want the original item clicked in A to be replaced with the data received from the intent from B.
ArrayAdapter<Comment> adapter = new ArrayAdapter<Comment>(this,
android.R.layout.simple_list_item_1, values);
// setListAdapter(adapter);
final ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
//intent receiving data from Activity B; I want to add in statement to change the original item clicked to this new String, edit;
Bundle fromedit = getIntent().getExtras();
if (fromedit != null) {
String edit = fromedit.getString("BENG");
int ps = fromedit.getInt("POSITION");
}
//onclicklistener for the listview
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(Notes.this, EditNote.class);
intent.putExtra("KEY", values.get(position).toString());
intent.putExtra("POSITION", position);
startActivity(intent);
}
});
Thanks!
In your original activity you need to keep an int variable referring to the selected item index on the list. So your onItemClick() would look like that:
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
currentSelected = position;
Intent intent = new Intent(Notes.this, EditNote.class);
intent.putExtra("KEY", values.get(position).toString());
intent.putExtra("POSITION", position);
startActivity(intent);
}
When you return from the activity where you modify the data you need to update the item of your values list and call adapter.notifyDataSetChanged().
Have you tried to update your list by calling mList.set(index, Object); and then refreshing the Adapter to update ListView displayed data?
You can use the ArrayList#set() method, thus if your 'values' dataset is an ArrayList.
The java.util.ArrayList.set(int index, E element) replaces the element at the specified position in this list with the specified element.
modify your code as follows:
//intent receiving data from Activity B; I want to add in statement to change the original item clicked to this new String, edit;
Bundle fromedit = getIntent().getExtras();
if (fromedit != null) {
String edit = fromedit.getString("BENG");
int ps = fromedit.getInt("POSITION");
values.set(ps, edit);
adapter.notifyDataSetChanged();
}

How to Get the SQLite column _id value for the list item clicked in listview

I have an activity which show a list. The list is populated from data taken from a sqlite database. I'm using a simpleCursorAdapter. When an item in the list is clicked I want go to another activity page to show more details about the list item clicked. For that I need the _id(primary key) of the clicked list item which is given in the database, so that I can query the database with that id and show more details in the next activity that loads when user clicks the list item.By using onItemClickListener, How to do this??? I appreciate any suggestions. Thanks in advance!
Set _id(primary key) as ID for list item:Adapter of data
Adapter:
#Override
public long getItemId(int position) {
return position;//you can return your ID
}
Activity:
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//id == getItemId(int position);
}
});
also do:
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//listView.getAdapter().getItem(position) -> getId;
}
});
You can pass the Id with an intent to the next activity:
Intent intent = new Intent(this, your_next_activity.class);
intent.putExtra("ID", id);
startActivity(intent);
Then get the value inside the next activity (EDIT):
Intent intent = getIntent();
int id= intent.getIntExtra("ID", 0);
Then You have the ID and You can query the database:
Cursor c = yourDBHelper.getAllDetailsMethod(); //method inside Your db-helper that gives You the cursor
int rows = c.getCount();
c.moveToFirst();
for(int i=0;i<rows;i++){
int db_id = c.getInt(0) //this belongs to the place where Your id is inside the db
if(db_id==id){
//here You can get all details you need
break;//stop quering
}else{
c.moveToNext();
}
}
But to give You a good solution it will be good if You show us what You have done until now.

AutoCompleteTextView click event on Android

I have successfully implemented my AutoCompleteTextView which is based off an SQLite query and is placed in an array adapter. That's all working beautifully, however I can't get my onclickevent working.
I just want to create an intent to pass the selected value to a new activity. I know how to create an onclicklistener. I am just unsure about how to apply it to the dropdown box of the AutoCompleteTextView.
Nevermind. I've solved it. I was just executing poorly. The code below autocompletes my textview based off a simple SELECT SQLite statement and executes when the user selects the university from the dropdown list.
The onclick event creates a new intent and starts a new activity passing the selection to this activity within the intent.
final AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.ac_university);
String[] universities = myDbHelper.getAllUnis(db);
// Print out the values to the log
for(int i = 0; i < universities.length; i++)
{
Log.i(this.toString(), universities[i]);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, universities);
textView.setAdapter(adapter);
//textView.setOnItemSelectedListener(this);
textView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Intent intent = new Intent(Main.this, Campus.class);
Bundle bundle = new Bundle();
bundle.putString("university_name", arg0.getItemAtPosition(arg2).toString());
bundle.putLong("_id", arg3);
intent.putExtras(bundle);
startActivity(intent);
}
putExtra function can be used for this purpose.
Here is an example...
Form the sending activity:
lv.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
ApplicationInfo x = appinstalled.get(pos);
PackageInfo y = appinstall.get(pos);
//Intent i = new Intent(InstalledPackages.this, Information.class);
i = new Intent(InstalledPackages.this, Information.class);
i.putExtra("i",x);
i.putExtra("j", y);
startActivity(i);
}
});
}
On the receiving side:
super.onCreate(savedInstanceState);
Intent myIntent = getIntent();
ApplicationInfo i = (ApplicationInfo)myIntent.getParcelableExtra("i");
PackageInfo j = (PackageInfo)myIntent.getParcelableExtra("j");

Categories

Resources