An IF statement in a cursor adapter? - java

private void datafill()
{
Cursor notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
/* JournalRowId is the row id from the first database containing all journal names
All notes are kept in database 2. I want only the notes that correspond to each
journal to be listed, KEY_HOMEID is the non visible field that shows where
each note came from.
*
*/
if (editjournalDbAdapter.KEY_HOMEID == journalRowId){
String[] from = new String[]{editjournalDbAdapter.KEY_HEIGHT};
int[] to = new int[]{R.id.detail1};
}
//Error here "from" and "to" are not defined outside of if statement
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.journaldetailrow, notesCursor, from, to);
setListAdapter(notes);
}

"from" and "to" only exist within the scope of the if() statement. Wouldn't make much sense otherwise anyway - even if they did, their contents would be undefined (or, in case of Java, null) and immediately crash your app.
I have no idea what you're trying to accomplish, but you probably want the bottom two statements inside the if() block as well.

Related

Android - SQLite database not updating row

I have looked at the plethora of similar topics for the past couple days but none seem to help my actual situation or maybe it's just my inexperience.
I have a simple application that performs CRUD operations. I can successfully enter new rows into the table as well as delete them, however something is wrong with my update code and I can't find why. What has me puzzled is it worked once, then never did again regardless if I create new entries or delete the database entirely and start again. Isolating what I think the relevant code would be the operation flow is as follows.
The individual items are inside a RecyclerView and are sent from an inner class to the activity to be edited and updated:
public void onBindViewHolder(#NonNull ContactViewHolder holder, int position) {
final String contactName = mCursor.getString(mCursor.getColumnIndex(ContactEntry.COLUMN_NAME));
final int contactNumber = mCursor.getInt(mCursor.getColumnIndex(ContactEntry.COLUMN_PHONE_NUMBER));
final String contactMail = mCursor.getString(mCursor.getColumnIndex(ContactEntry.COLUMN_EMAIL));
final int currentPosition = position;
holder.mEditContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ContactUpdate.class);
intent.putExtra(CONTACT_POSITION, currentPosition);
intent.putExtra(EXTRA_NAME, contactName);
intent.putExtra(EXTRA_PHONE, contactNumber);
intent.putExtra(EXTRA_MAIL, contactMail);
mContext.startActivity(intent);
}
});
Then I get them in the retrieving class and organise the values into the appropriate EditText views. I'm sure there is a more efficient way but I'm still learning:
Intent intent = getIntent();
mPosition = intent.getIntExtra(ContactRecyclerAdapter.CONTACT_POSITION, 0);
mContactName = intent.getStringExtra(ContactRecyclerAdapter.EXTRA_NAME);
mContactPhone = intent.getIntExtra(ContactRecyclerAdapter.EXTRA_PHONE, 0);
mContactMail = intent.getStringExtra(ContactRecyclerAdapter.EXTRA_MAIL);
mUpdateName.setText(mContactName);
mUpdatePhone.setText("" + mContactPhone);
mUpdateMail.setText(mContactMail);
Lastly my method to update the row:
private void updateData() {
String name = mUpdateName.getText().toString();
String getPhone = mUpdatePhone.getText().toString();
int phone = Integer.parseInt(getPhone);
String mail = mUpdateMail.getText().toString();
SQLiteDatabase db = new ContactOpenHelper(this).getWritableDatabase();
ContentValues values = new ContentValues();
values.put(ContactEntry._ID, mPosition);
values.put(ContactEntry.COLUMN_NAME, name);
values.put(ContactEntry.COLUMN_PHONE_NUMBER, phone);
values.put(ContactEntry.COLUMN_EMAIL, mail);
String selection = ContactEntry._ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(mPosition)};
db.update(ContactEntry.TABLE_NAME, values, selection, selectionArgs);
db.close();
startActivity(new Intent(this, ContactList.class));
}
What is happening is the row is not being updated. Currently I have three mock entries entered. I put a break point at the update() line to try and find out what is happening. The original name for the this entry is "ted" and it's the third in the list. If I edit the EditText field and run the updateData() method, when the break point is hit it correctly shows the edited value as well the correct position of 2. However the database doesn't actually update. I am clearly misunderstanding how something works here.
To avoid bloat I have only included what I think is pertinent, but if anymore info is required then I'm happy to add.
Lastly here is a screen shot of the debugger at the break point showing what I perceive to be the correct information and where I'm completely confused as to why it is not working (I added a bunch of g's on the end of the name "ted" just to test if it would work).
Chnage your call to update as below
int count = db.update(ContactEntry.TABLE_NAME, values, selection, selectionArgs);
where count shows the number of the rows afftected with the update function, this would help you know exactly if there was any updated row or not.
Note :-We use like when, sometimes, you don’t know exactly the complete keyword that you want to query. For example, you may know that your most favorite song contains the word,elevator but you don’t know exactly the name.
If you know the exact value try to use:-
String selection = ContactEntry._ID + " =? ";
String selection = ContactEntry._ID + " LIKE ?";
String[] selectionArgs = { String.valueOf(mPosition)};
Update this above code to this below code
String selection = ContactEntry._ID + " = ?";
String[] selectionArgs = { String.valueOf(mPosition)};
You want to update an exact row. But 'LIKE' keyword mostly uses for searches.
Besides, You are opening your activity when you update your data. Update or insert in database takes some time. When your next activity start, database may not finish its write operation. It could lead you to see the previous data. Make sure your database is updated and then update the view.
See your database from emulator that database has the new value or not. Then do the further work.
Try to delete you _Id from contentValues:
//values.put(ContactEntry._ID, mPosition);
I think you can't change PRIMARY_KEY, you say what line you want to update in:
String[] selectionArgs = { String.valueOf(mPosition)};
I have now solved this particular problem and the answer was quite simple and a little embarrassing. I was trying to use the cursor position for the row ID not realising that the database isn't using a zero-base index like the cursor, hence the primary key was not matching.
As I am using a RecyclerView I added the following line to my onBindViewHolder and passed the variable to my update activity which then could be used in the selectionArgs
final long id = mCursor.getLong(mCursor.getColumnIndex(ContactEntry._ID));

Order a ParseQuery by the date at which only one field has been updated

I have a feed containing posts that are currently ordered by "updatedAt". My original intention was to push up posts to the top of the feed which were last replied to (I do this by incrementing a "replyCount" field in each post when a user leaves a comment), not totally cognizant of the fact that another field, "likeCount" is also being updated when user's "like" a post. I would still like to push those posts that were recently "replied to" to the top of the feed, but do not at the expense of the weird UX behavior that associated with liking posts pushing them up as well. I'm not sure how to separate the two.
What should I do here? Can I maybe add another column called "lastReplyCountTime" and then sort queries based on that? Maybe set lastReplyCountTime for all posts to the current time when saved to the database, and then only update that value when a post receives a reply?
String groupId = ParseUser.getCurrentUser().getString("groupId");
ParseQuery<ParseObject> query = new ParseQuery<>(ParseConstants.CLASS_POST);
query.whereContains(ParseConstants.KEY_GROUP_ID, groupId);
/*query.addDescendingOrder(ParseConstants.KEY_CREATED_AT);*/
query.orderByDescending("updatedAt");
query.findInBackground((posts, e) -> {
if (mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}
if (e == null) {
// We found messages!
mPosts = posts;
String[] usernames;
usernames = new String[mPosts.size()];
int i = 0;
for(ParseObject post : mPosts) {
usernames[i] = yeet.getString(ParseConstants.KEY_SENDER_NAME);
i++;
}
FeedAdapter adapter = new FeedAdapter(
getListView().getContext(),
mYeets);
setListAdapter(adapter);
}
});
}
You have 2 options:
Like you suggested you can create another date property let's call it sortedUpdatedAt and update it with the current date each time you are updating the relevant values
If you still want to use updatedAt you can wrap your like object in a separate parse object (class). This class will be saved as a relation in the parent class and then each time the user "like" you can just update only this class and not the whole object. This way the updatedAt of your parent object will not be changed.
I think that option 1 is great since it's not so complicated and you can do it very quick.

SQLite Cursor returning the value for one column as the value for all columns

I am attempting to read from an SQLite database I have created containing information on UK universities.
The table has the following columns:
Institution
Rank_2017
Guardian_score100
Satisfied_with_course
Satisfied_with_teaching
Satisfied_with_feedback
Student_to_staff_ratio
Average_entry_tariff
Career_after_6_months
I have populated the table from a CSV file, and then attempted to call a getUni() method that will return the information in each of the columns, and use them to build a University object, however when I check the values of each member variable of University, the name and rank have been set appropriately, however every variable after that has also been set to the value of Rank_2017.
getUni() Method
public University getUni(String id)
{
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_UNIVERSITIES, COLUMNS, " Institution = ?",
new String[] { id }, null, null, null, null);
if(cursor != null){
cursor.moveToFirst();
}
System.out.println("###" + cursor.getCount() + "###");
University uni = new University();
if(cursor != null){
uni.setUni_name(cursor.getString(0));
uni.setRank(cursor.getString(1));
uni.setGuardianScore(cursor.getString(2));
uni.setCourseSatisfaction(cursor.getString(3));
uni.setTeachingSatisfaction(cursor.getString(4));
uni.setFeedbackSatisfaction(cursor.getString(5));
uni.setStudentStaffRatio(cursor.getString(6));
uni.setAverageEntryTariff(cursor.getString(7));
uni.setCareerAfterSixMonths(cursor.getString(8));
}
// return University
return uni;
}
After calling cursor.getColumnCount() i can see that it returns 10 columns as expected, however something isn't quite right.
For example, if I call University uni = getUni("Glasgow"); , it will assign both the University name, and rank_2017 correctly, however assign each member variable after that the same as rank_2017.
CSV row example:
Glasgow,26,70.8,89.3,91.6,67.3,14.5,478.4,78.5
Any help solving this issue would be hugely appreciated.
I suspect when you imported the CSV file, it didn't work correctly. Perhaps you didn't specify a separator, and SQLite created a table for you with only one column. Or it populated the table strangely, and your SQL adapter is "helping" in a surprising way. That could happen if for instance your CSV file had some whitespace.
I would use the SQLite shell to verify that the Glassgow row appears as expected in the database. That at least will let you distinguish between SQLite issues and Java library issues (if any).
HTH.

How to use a get method for a SQLite Database management class in another class?

What I am trying to do is retrieve an ArrayList from another database manager class. Unfortunately all I can do because the manager class cannot work statically is create an instance in another class, then call the method. Then I got myself into passing that same instance into the method which asked for an SQLiteDatabase object. Now I've worked myself into a bind of confusion, when all I really want is to do is retrieve the arraylist to display a listview of elements from an SQL column.
EDIT: My post lacked clarity, so I'll try to specify exactly what is going wrong and what I am trying to accomplish here:
In a display (output) activity, I am trying to use a ListView to display elements contained in an SQL database. Currently, I am only focusing on one column (Assignment Names). My approach involved using a get method built into the database manager class, but because you cannot reference that method statically, I tried to use the method by creating an instance of that manager class. This would return an ArrayList of Inputted objects (each containing a name). It seemed to have worked, but when running the program, the LogCat protested that I was calling getDatabase recursively. After looking online, people recommended that I fix the issue by changing the method to ask for (SQLiteDatabase db) as parameters so the same database gets tossed around in the manager. Now I get confused here-- I'm not sure what to pass into this method from the display activity. It also doesn't help that from what I've heard from the comments, my get method doesn't traverse the SQL database properly. If you can solve this puzzle THANK YOU!
I'll post my code for diagnosis, hopefully an outside view will show exactly what's wrong with everything I'm trying here.
public Cursor getAssignmentNames(SQLiteDatabase db) {
return db.query(false, ASSIGNMENT_TABLE, COLUMN_TITLES,
" WHERE " + ASSIGNMENT_NAME + " ", null, null, null, " ORDER BY "+ASSIGNMENT_URGENCY_RATING, null);
}
/
public ArrayList<Inputted> getListOfAssignments (SQLiteDatabase db) {
Cursor names = getAssignmentNames(db);
ArrayList<Inputted> assList = new ArrayList<Inputted>();
names.moveToFirst();
while (!cursorsAreAfterLast(names) ) {
int go = 0;
assList.add(new Inputted(names.getString(go))
names.moveToNext();
go++;
}
return assList;
}
/
DBRecordsLayer assignmentRecords = new DBRecordsLayer(this,
"assignment.db", null, 1);
ArrayList<Inputted> assList = DBRecordsLayer.getListOfAssignments(assignmentRecords);
Your code is a bit confusing... In each iteration of the while loop, you are incrementing the cursor (names.moveToNext()); You are also incrementing go.
The result would be:
1st iteration: You are taking the data from the first column of the first query
2nd iteration: You are taking the data from the second column of the second query
etc...
I'm assume that you want to be reading data from the same column of the database for each iteration.
try this:
public ArrayList<Inputted> getListOfAssignments (SQLiteDatabase db) {
Cursor names = getAssignmentNames(db);
ArrayList<Inputted> assList = new ArrayList<Inputted>();
names.moveToFirst();
columnContainingStringToSendToInputtedConstructor = x; //replace the x with column you need from your table
while (!names.isAfterLast()) {
assList.add(new Inputted(names.getString(columnContainingStringToSendToInputtedConstructor));
names.moveToNext();
}
}

Android - how to delete item from a cursor?

Let's say I make the following cursor to get the call log of someone:
String[] strFields = {
android.provider.CallLog.Calls.NUMBER,
android.provider.CallLog.Calls.TYPE,
android.provider.CallLog.Calls.CACHED_NAME,
android.provider.CallLog.Calls.CACHED_NUMBER_TYPE
};
String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
Cursor mCallCursor = getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI,
strFields,
null,
null,
strOrder
);
Now how would I go about deleted the ith item in this cursor? This could also be a cursor getting list of music, etc. So then I must ask - is this even possible? I can understand for certain cursors that 3rd party apps wouldn't be allowed to delete from.
Thanks.
Sorry mate you can't delete from a cursor.
You must either use your ContentResolver or a SQL call of some sort..
You can to a trick with a MatrixCursor. With this strategy, you copy the cursor, and leave out the one row you want to exclude. This is - obviously, not very efficient for large cursors as you will keep the entire dataset in memory.
You also have to repeat the String array of column names in the constructor of the MatrixCursor. You should keep this as a Constant.
//TODO: put the value you want to exclude
String exclueRef = "Some id to exclude for the new";
MatrixCursor newCursor = new MatrixCursor(new String[] {"column A", "column B");
if (cursor.moveToFirst()) {
do {
// skip the copy of this one ....
if (cursor.getString(0).equals(exclueRef))
continue;
newCursor.addRow(new Object[]{cursor.getString(0), cursor.getString(1)});
} while (cursor.moveToNext());
}
I constantly battle with this; trying to make my apps with cursors and content providers only, keeping away from object mapping as long as I can. You should see some of my ViewBinders ... :-)

Categories