android cardview only show the last result the right amount of times - android-cardview

i'm new to android and java.
i made a cardview and populated it with a simple loop like so:
private ArrayList<DataObject> getTheData(){
ArrayList res = new ArrayList<DataObject>();
for (int index = 0; index < 5; index++){
DataObject obj = new DataObject("shit","happen");
res.add(index,obj);
}
return res;
}
it worked. now i created a database and want to populate it with this data. so i have this:
public ArrayList<DataObject> getData() {
SQLiteDatabase db = this.getReadableDatabase();
ArrayList res = null;
try {
res = new ArrayList<DataObject>();
String selectQuery = "SELECT * FROM quotes a LEFT JOIN authors b ON b.author_id=a.quote_author";
Cursor cursor = db.rawQuery(selectQuery, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
Log.d("CHECKDB",cursor.getString(cursor.getColumnIndex("first_name")) + " " + cursor.getString(cursor.getColumnIndex("last_name")));
Log.d("CHECKDB2",cursor.getString(cursor.getColumnIndex("quote_text")));
DataObject obj = new DataObject(
cursor.getString(cursor.getColumnIndex("first_name")) + " " + cursor.getString(cursor.getColumnIndex("last_name")),
cursor.getString(cursor.getColumnIndex("quote_text"))
);
res.add(obj);
} while (cursor.moveToNext());
}
}
} catch (SQLiteException se) {
Log.e(getClass().getSimpleName(), "Could not create or Open the database");
} finally {
if (db != null)
db.close();
}
return res;
}
the log show all the results, but when i run the app i get the last result the right amount of times. in this case 4 quotes in my database, so i see 4 but the last one 4 times.
please , since i'm new to it, good explanations will be appreciated.

the issue was that my dataobject attributes were set to static

Related

Android cursor.getColumnNames() doesn't contain the new added column

I use code below to test if a column exists:
public static boolean isColumnExists(String tableName, String columnName) {
Cursor cursor = null;
try {
SQLiteDatabase db = getDatabase();
cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null);
String[] cloNames = cursor.getColumnNames();
if (cloNames != null) {
for (String temp : cloNames) {
if (columnName.equalsIgnoreCase(temp)) {
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != cursor && !cursor.isClosed()) {
cursor.close();
}
}
return false;
}
The column hello2 doesn't exist in initial state, after adding column to database, the following test still tells that the column doesn't exist, and the second try will cause an error about duplicate column, which is not correct.
if (!isColumnExists("PositionCache", "hello2")) {
// First try will insert column to database
getDatabase().execSQL("alter table PositionCache add hello2 Integer default 0");
}
if (!isColumnExists("PositionCache", "hello2")) {
// Second try will give and error about duplicate column of hello2
getDatabase().execSQL("alter table PositionCache add hello2 Integer default 0");
}
I need to know the reason about such an abnormal phenomenon.
If I change SELECT * FROM to select * from in method isColumnExists then everything become normal.
I believe the reason is that SQLite (I strongly suspect the Cursor, so more correctly the Android SQLite aspect of the SDK) is cacheing data (perhaps because the underlying data is never retrieved from the Database as there is no need to get the data (as far as the Cursor is concerned)).
I've tried various checks including putting breakpoints in, checking the result of getColumnnames, and making the method non-static.
As soon as I add an alternative check using the PRAGMA table_info(*table_name*); then the column exists.
As such I'd suggest using the following :-
public static boolean isColumnExistsOld(String tableName, String columnName) {
Cursor csr = getDatabase().rawQuery("PRAGMA table_info(" + tableName + ")",null);
while(csr.moveToNext()) {
if (csr.getString(csr.getColumnIndex("name")).equalsIgnoreCase(columnName)) {
return true;
}
}
return false;
/*
Cursor cursor = null;
try {
SQLiteDatabase db = getDatabase();
cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null);
cursor.moveToFirst();
String[] cloNames = cursor.getColumnNames();
if (cloNames != null) {
for (String temp : cloNames) {
if (columnName.equalsIgnoreCase(temp)) {
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != cursor && !cursor.isClosed()) {
cursor.close();
}
}
boolean rv = colfound;
return false;
*/
}
Note your code has been left in but commented out.
I believe that evaluating forces the cache to be refreshed (i.e. I tried this an yep it does dynamically change to include the column).

How to store database column in ArrayList in android?

Here I want to store data in ArrayList visible Sections please help me...
Here's my code.
public DataSingleton() {
try {
db = openOrCreateDatabase("/sdcard/Download/Nanhikali_db.db", Context.MODE_PRIVATE, null);
Cursor c = db.rawQuery("select label from nanhikali where level = 1", null);
if (c.moveToFirst()) {
while (c.moveToNext()) {
String lb = c.getString(c.getColumnIndex("label"));
visibleSections.add(lb);
visibleSections = new ArrayList<>();
}
}
}
catch(Exception e)
{
}
Your column string maybe wrong:
Try like this.
if(c.moveToFirst()){
while(c.moveToNext()){
String lb = c.getString(c.getColumnIndex("label"));
visibleSections.add(lb);
}
}
Not "lebel".
You are re assigning the array list every time your loop iterates.
remove visibleSections = new ArrayList<>(); from your loop.
and use While Loop as
while(!cursor.isAfterLast())
{
//get All data here then
cursor.moveToNext();
}

Android: Display Image From SQLite

I'm learning about databases in android and have come across the following question, I would like to retrieve an image, how can I change the code below to image instead of string?
public List<String> getImage(){
List<String> listRows = new ArrayList<String>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor c;
try {
c = db.rawQuery("SELECT image FROM " + MY_TABLE + " WHERE _id = " + _id, null);
if(c == null) return null;
String row;
c.moveToFirst();
do {
row = c.getString(0);
listRows.add(row);
} while (c.moveToNext());
c.close();
}
catch (Exception e) {
Log.e("LOGmsg getDBImage", e.getMessage());
}
db.close();
return listRows;
}
store the image in the database is a bad practice, it is better to store pictures on the sd and store in the database paths to them
Treat the image as a byte array and write/retrieve it to/from your database as a Blob object.

SQLite: no such table: while compiling

I've got a long running task that I run onResume on my activity. The task involves querying a database then decrypting some data, then manually sorting it then updating the sort order in the database using a transaction.
This works fine when I run it from the Activities main UI thread, but when I execute the same task from within an AsyncTask I always get these errors:
I/SqliteDatabaseCpp(5166): sqlite returned: error code = 1, msg = no such table: Household, db=/mnt/sdcard/myDatabase.db
no such table: while compiling: no such table: Household: , while compiling: SELECT DISTINCT street FROM Household WHERE street IS NOT NULL AND LENGTH(LTRIM(RTRIM(street)))>0
I know that the database exists and that SQL statement is fine because it runs fine outside the AsyncTask. Is there something about access my database from within an AsyncTask that causes problems?
I'm getting errors on the "SELECT DISTINCT" raw query below.
private boolean update_street_sort_order() {
boolean returnValue = false;
DBUtilities objDbUtil = null;
Cursor cCases = null;
final String SORT_ATTRIBUTE = "street_sort_order";
final int STREET_INDEX = 0;
final int ENCRYPTED_STREET = 0;
final int DECRYPTED_STREET = 1;
try {
objDbUtil = DBUtilities.getInstance(this);
if (objDbUtil != null) { // Get list of cases
ArrayList<String[]> alStreet = new ArrayList<String[]>();
SQLiteDatabase sqlitedatabase = objDbUtil.getDatabase();
if (sqlitedatabase != null && sqlitedatabase.isOpen()) {
cCases = sqlitedatabase.rawQuery("SELECT DISTINCT street "
+ "FROM Household " + "WHERE street IS NOT NULL "
+ "AND LENGTH(LTRIM(RTRIM(street)))>0", null);
String _password = this.context.getPassword();
if (cCases != null && cCases.moveToFirst()) {
do { // Create list of en/decrypted streets
alStreet.add(new String[] {
cCases.getString(STREET_INDEX),
Crypto.decrypt(_password,
cCases.getString(STREET_INDEX)) });
} while (cCases.moveToNext());
}
if (cCases != null) {
cCases.close();
cCases = null;
}
int alStreet_length = alStreet.size();
if (alStreet_length > 0) {
Collections.sort(alStreet, new Comparator<String[]>() {
#Override
public int compare(String[] lhs, String[] rhs) {
return lhs[DECRYPTED_STREET]
.compareToIgnoreCase(rhs[DECRYPTED_STREET]);
}
}); // sort decrypted street using custom comparator
StringBuilder sql_transaction = new StringBuilder(
"BEGIN TRANSACTION;" + "UPDATE Household SET "
+ SORT_ATTRIBUTE + "=NULL;");
for (int i = 0; i < alStreet_length; i++) {
sql_transaction.append(String.format(
"UPDATE Household " + "SET "
+ SORT_ATTRIBUTE + "=%1$d "
+ "WHERE street=\"%2$s\";", i,
alStreet.get(i)[ENCRYPTED_STREET]));
}
sql_transaction.append("COMMIT;");
// execute transaction
sqlitedatabase.execSQL(sql_transaction.toString());
}
returnValue = true;
}
}
} catch (Exception e) {
Log.e(Utilities.getFullMethodName(e), e.getMessage());
} finally {
if (objDbUtil != null) { // release resources
objDbUtil.close();
objDbUtil = null;
}
}
return returnValue;

Getting data from sqlite on android is really slow

I have this code:
DatabaseHandler db = new DatabaseHandler(this);
System.out.println("Start - " + System.currentTimeMillis());
for (int i = 1; i < db.getChampsCount() + 1; i++) {
String name = db.getChampInfo(i, "name");
String title = db.getChampInfo(i, "title");
String thumb = db.getChampInfo(i, "thumb");
System.out.println("End - " + System.currentTimeMillis());
[...]
}
and this
String getChampInfo(int id, String col) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT " + col + " FROM champions WHERE id = " + id, new String[] {});
if (cursor != null)
cursor.moveToFirst();
db.close();
return cursor.getString(0);
}
Which is a part of DatabaseHelper class
And it works ok, but the problem is it takes way too long to execute (2089ms on my android phone). Those strings are a part of the UI so I don't think I can put that in another thread. What can i do to make this code run faster?
Edit: there are exactly 110 rows
Instead of individual statement, should you not use Single sql statement ?
Just create one ArrayList which will store all the required value in the Activity class.
e.g: ArrayList<String> myData;
Now in database helper class make one function like below:
// TO get All Data of datanase which you want
public ArrayList<String> getAllData() {
ArrayList<String> subTitleList = null;
Cursor cursor = null;
try {
String queryString = "SELECT * FROM champions";
cursor = db.rawQuery(queryString, null);
if (cursor != null && cursor.moveToFirst()) {
subTitleList = new ArrayList<String>();
do {
String nextUser = new String(cursor.getString(cursor.getColumnIndex("name")));
String nextUser = new String(cursor.getString(cursor.getColumnIndex("title")));
String nextUser = new String(cursor.getString(cursor.getColumnIndex("thumb")));
subTitleList.add(nextUser);
}
while (cursor.moveToNext());
System.out.println("it comes in SubTitleList");
}
}
catch (Exception e) {
e.printStackTrace();
subTitleList = null;
}
finally {
if (cursor != null && !cursor.isClosed()) {
cursor.deactivate();
cursor.close();
cursor = null;
}
if(db != null){
db.close();
}
}
//System.out.println("SubTitleList is: "+subTitleList);
return subTitleList;
}
And now in your activity class you can call this function and get all the required data from the myData ArrayList.
myData = db.getAllData(); // i think there is no need of any ID if you are fetching all the data.
Hope you got my point.
You can definitely run those in an AsyncTask. All you have to do is pass the data into the task's parameters or if you cant figure that out just make your task have a constructor that takes the parameters and call it like this:
MyAsync ma = new MyAsync(stuff, stuff, stuff);
ma.execute();
In the task's onPostExecute() is where you can grab the data from your queries that ran in the background and then you can update the UI.
Also the other guys are kind of right. If you can combine your queries that would be best but with a table like that its not really going to give you much of a performance boost, at least I don't think.

Resources