Passing an object through Activities (Android) - java

For my software engineering class, we have to incorporate an SQLite database into our application project.
For our application this database class has to be accessible from multiple activities. I have turned the Database class into a singleton and then call
DBInterface database = Database.getInstance(this)
to set a variable to reference the database in order to access its methods in each necessary class and it works. However, we are supposed to utilize dependency injections into our code and my professor has specifically told us that it should be possible to switch from our database class to a stub database we used in a previous iteration by only changing one line of code.
Obviously this means changing the above to
DBInterface database = StubDB.getInstance(this)
However in doing this I still have to make this change in each of the activities that uses the database methods.
So my question is this: is there a way to initialize my database in our init activity and then pass a reference to each necessary activity without the assignment code above?
Relevant Code
Singleton Database Class
public class RecipeDatabase extends Activity implements DBInterface {
private dbHelper Helper;
private static RecipeDatabase sInstance;
private static Context sContext;
public static synchronized RecipeDatabase getInstance(Context context){
if(sInstance == null){
sInstance = new RecipeDatabase(context.getApplicationContext());
}
return sInstance;
}
private RecipeDatabase(Context context){
Helper = new dbHelper(context);
sContext = context;
}
#Override
public void addRecipe(Recipe recipe)
{
String ingredients = recipe.ingredientString();
String directions = recipe.directionString();
SQLiteDatabase db = Helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Recipe.KEY_rID, recipe.getrID());
values.put(Recipe.KEY_mealtype, recipe.getMealType());
values.put(Recipe.KEY_mainingredient, recipe.getMainIngredient());
values.put(Recipe.KEY_description, recipe.getDescription());
values.put(Recipe.KEY_ingredients, ingredients);
values.put(Recipe.KEY_directions, directions);
values.put(Recipe.KEY_notes, recipe.getNotes());
values.put(Recipe.KEY_rating, recipe.getRating());
values.put(Recipe.KEY_cooktime, recipe.getCooktime());
db.insert(Recipe.TABLE, null, values);
db.close();
}
#Override
public void editRecipe(Recipe recipe)
{
SQLiteDatabase db = Helper.getWritableDatabase();
ContentValues values = new ContentValues();
String ingredients = recipe.ingredientString();
String directions = recipe.directionString();
values.put(Recipe.KEY_rID, recipe.getrID());
values.put(Recipe.KEY_mealtype, recipe.getMealType());
values.put(Recipe.KEY_mainingredient, recipe.getMainIngredient());
values.put(Recipe.KEY_description, recipe.getDescription());
values.put(Recipe.KEY_ingredients, ingredients);
values.put(Recipe.KEY_directions, directions);
values.put(Recipe.KEY_notes, recipe.getNotes());
values.put(Recipe.KEY_rating, recipe.getRating());
values.put(Recipe.KEY_cooktime, recipe.getCooktime());
db.update(Recipe.TABLE, values, Recipe.KEY_rID + " = ?", new String[]{String.valueOf(recipe.getrID())});
db.close();
}
#Override
public void deleteRecipe(Recipe recipe)
{
SQLiteDatabase db = Helper.getWritableDatabase();
db.delete(Recipe.TABLE, Recipe.KEY_rID + " = ", new String[]{String.valueOf(recipe.getrID())});
db.close();
}
public ArrayList<Recipe> getList()
{
ArrayList<Recipe> result = new ArrayList<>();
SQLiteDatabase db = Helper.getReadableDatabase();
String selectQuery = "SELECT " + Recipe.KEY_rID + ", " +
Recipe.KEY_name + ", " +
Recipe.KEY_mealtype + ", " +
Recipe.KEY_mainingredient + ", " +
Recipe.KEY_description + ", " +
Recipe.KEY_ingredients + ", " +
Recipe.KEY_directions + ", " +
Recipe.KEY_notes + ", " +
Recipe.KEY_rating + ", " +
Recipe.KEY_cooktime + " FROM " + Recipe.TABLE;
Cursor cursor = db.rawQuery(selectQuery, null);
if(cursor.moveToFirst()) {
do {
ArrayList<String> ingredients = new ArrayList<>(); // Temp Storage
ArrayList<String> directions = new ArrayList<>(); // Temp Storage
String tempIngredient = cursor.getString(cursor.getColumnIndex(Recipe.KEY_ingredients));
String[] temp = tempIngredient.split("- "); //Split up ingredients to individual strings
for(int x=0; x < temp.length; x++) {
ingredients.add(temp[x]);
}
String tempDirection = cursor.getString(cursor.getColumnIndex(Recipe.KEY_ingredients));
temp = tempDirection.split("- ");//split up directions into individual strings
for(int x=0; x < temp.length; x++) {
directions.add(temp[x]);
}
//Get Values for Recipe Object
int rID = cursor.getInt(cursor.getColumnIndex(Recipe.KEY_rID));
String name = cursor.getString(cursor.getColumnIndex(Recipe.KEY_name));
String mealType = cursor.getString(cursor.getColumnIndex(Recipe.KEY_mealtype));
String mainIngredient = cursor.getString(cursor.getColumnIndex(Recipe.KEY_mainingredient));
int rating = cursor.getInt(cursor.getColumnIndex(Recipe.KEY_rating));
String description = cursor.getString(cursor.getColumnIndex(Recipe.KEY_description));
int cooktime = cursor.getInt(cursor.getColumnIndex(Recipe.KEY_cooktime));
String notes = cursor.getString(cursor.getColumnIndex(Recipe.KEY_notes));
//Create new Recipe from Row
Recipe tempRecipe = new Recipe(rID, name, description, mealType, mainIngredient,
rating, cooktime, notes, ingredients, directions);
//Add the recipe to the ArrayList
result.add(tempRecipe);
}while (cursor.moveToNext());
}
//Return the populated ArrayList for use
return result;
}
}
Init Class
public class init extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_init);
//The code to change to switch from stub to database
DBInterface repository = RecipeDatabase.getInstance(this);
//DBInterface repository = new StubDB(this);
ArrayList<Recipe> recipes = repository.getList();
ArrayList<String> recipeDisplay = new ArrayList<>();
for(int i=0; i<recipes.size(); i++) {
recipeDisplay.add(recipes.get(i).getName());
}
ArrayAdapter<String> myArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, recipeDisplay);
ListView lv = this.getListView();
lv.setAdapter(myArrayAdapter);
}
#Override
protected void onListItemClick(ListView l, View v, int pos, long id){
super.onListItemClick(l, v, pos, id);
Intent myIntent = new Intent(this, Details.class);
myIntent.putExtra("recipePosition", pos);
startActivity(myIntent);
}
public void shoppingListButton(View view){
startActivity(new Intent(this, ShoppingList.class));
}
public void addRecipeButton(View view){
Intent myIntent = new Intent(this, Edit.class);
myIntent.putExtra("editType", 1); // 1 corresponds to add recipe
startActivity(myIntent);
}
}
One of the Activity Classes that needs the DB methods
public class Details extends ListActivity {
int recipePosition = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
//want to avoid this call
DBInterface repository = RecipeDatabase.getInstance(this);
recipePosition = getIntent().getIntExtra("recipePosition", 0);
Recipe clickedRecipe = repository.getList().get(recipePosition);
ArrayList<String> recipeDetails = new ArrayList<>();
recipeDetails.add(clickedRecipe.getName());
recipeDetails.add(clickedRecipe.getDescription());
recipeDetails.add("Ingredients:");
for(int i=0; i<clickedRecipe.getIngredients().size(); i++){
recipeDetails.add(clickedRecipe.getIngredients().get(i));
}
recipeDetails.add("Instructions:");
for(int i=0; i<clickedRecipe.getDirections().size(); i++){
recipeDetails.add(clickedRecipe.getDirections().get(i));
}
ArrayAdapter<String> myArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, recipeDetails);
ListView lv = this.getListView();
lv.setAdapter(myArrayAdapter);
}
public void editButton(View view){
Intent myIntent = new Intent(this, Edit.class);
myIntent.putExtra("recipePosition", recipePosition);
myIntent.putExtra("editType", 2); // 2 corresponds to modify recipe
startActivity(myIntent);
}
}
Database Helper Class
public class dbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "ROSE.db";
public dbHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db){
//Creates the Recipe Table which stores recipes
String CREATE_TABLE_RECIPES = "CREATE TABLE " + Recipe.TABLE +
"(" + Recipe.KEY_rID + " INTEGER PRIMARY KEY, " +
Recipe.KEY_name + " TEXT, " +
Recipe.KEY_mealtype + " TEXT, " +
Recipe.KEY_mainingredient + " TEXT, " +
Recipe.KEY_description + " TEXT, " +
Recipe.KEY_ingredients + " TEXT, " +
Recipe.KEY_directions + " TEXT, " +
Recipe.KEY_notes + " TEXT, " +
Recipe.KEY_rating + " INTEGER, " +
Recipe.KEY_cooktime + " INTEGER )";
db.execSQL(CREATE_TABLE_RECIPES);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSQL("DROP TABLE IF EXISTS recipes" );
onCreate(db);
}
}

Dagger2 is the perfect thing for you. It's really easy to use, just follow the instructions they provide in the docs and you'll love it once you figure it out.
Basically you're going to use
#Inject
DBInterface database;
In every activity, fragment, service, or anywhere you wanna use the database.
Then you will create a DatabaseModule which will have a method that provides the database for injection.
#Singleton
#Provides static DBInterface provideDatabase() {
return new WhateverDatabaseImplementsDBInterface();
}
As you can see, just adding #Singleton will make it a singleton. And now changing the database you use is truly a one line change.
Dagger2 is the greatest thing you will encounter for dependency injection for sure, just setup it correctly, write if you have any trouble (but you shouldn't, with their thorough instructions).

You can use the SQLiteOpenHelper. It will make sure all your activities access the same database. Even if you have different database helper objects in each Activity, they all access the same database.

Related

How to Figure out the MAX and MIN of Groups that have been Added together

How do would you get the MAX value of a column that has been grouped and add together by _id.
So something like this:
I then want to display the MAX value of the four groups, as well as the MIN value of the four groups.
Something like this Scratch High = 702 / Scratch Low = 325
Is this possible with the built in Math functions of SQLite or would I need to write specific code to accomplish this? The actual number of groups will be more than 4, it will depend on how often the bowler actually bowls a series.
I haven't written any code for this as of yet, I am attempting to figure out if this is even possible before attempting to do so. Any suggestions would be welcome.
My attempt to integrate into my Project:
DatabaseHelper.java
public static final String DERIVEDCOL_MAXSCORE = "max_score";
public static final String DERIVEDCOl_MINSCORE = "min_score";
public Cursor getMaxMinScoresAllAndroid() {
SQLiteDatabase db = this.getWritableDatabase();
String tmptbl = "summed_scores";
String tmptblcol = "sum_score";
String crttmptbl = "CREATE TEMP TABLE IF NOT EXISTS " + tmptbl + "(" +
tmptblcol + " INTEGER" +
")";
String empttmptbl = "DELETE FROM " + tmptbl;
db.execSQL(crttmptbl);
db.execSQL(empttmptbl);
String[] columns = new String[]{"sum(score) AS " + tmptblcol};
Cursor csr = db.query(Game.TABLE_NAME,columns,null,null,Game.COLUMN_BOWLER_ID,null,null);
DatabaseUtils.dumpCursor(csr);
while (csr.moveToNext()) {
ContentValues cv = new ContentValues();
cv.put(tmptblcol,csr.getInt(csr.getColumnIndex(tmptblcol)));
db.insert(tmptbl,null,cv);
}
csr.close();
columns = new String[]{"max(" +
tmptblcol +
") AS " + DERIVEDCOL_MAXSCORE,
"min(" +
tmptblcol +
") AS " + DERIVEDCOl_MINSCORE};
return csr = db.query(tmptbl,columns,null,null,null,null,null);
}
public MaxMin getMaxAndminScoresAll() {
MaxMin rv = new MaxMin(0,0);
Cursor csr = getMaxMinScoresAllAndroid();
if (csr.moveToFirst()) {
rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
}
csr.close();
return rv;
}
BowlerProfileViewActivity.java
public class BowlerProfileViewActivity extends AppCompatActivity {
Bowler bowler;
private DatabaseHelper db;
private static final String PREFS_NAME = "prefs";
private static final String PREF_BLUE_THEME = "blue_theme";
private static final String PREF_GREEN_THEME = "green_theme";
private static final String PREF_ORANGE_THEME = "purple_theme";
private static final String PREF_RED_THEME = "red_theme";
private static final String PREF_YELLOW_THEME = "yellow_theme";
#Override
protected void onResume() {
super.onResume();
db = new DatabaseHelper(this);
//mAdapter.notifyDatasetChanged(db.getAllLeagues());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
//Use Chosen Theme
SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
boolean useBlueTheme = preferences.getBoolean(PREF_BLUE_THEME, false);
if (useBlueTheme) {
setTheme(R.style.AppTheme_Blue_NoActionBar);
}
boolean useGreenTheme = preferences.getBoolean(PREF_GREEN_THEME, false);
if (useGreenTheme) {
setTheme(R.style.AppTheme_Green_NoActionBar);
}
boolean useOrangeTheme = preferences.getBoolean(PREF_ORANGE_THEME, false);
if (useOrangeTheme) {
setTheme(R.style.AppTheme_Orange_NoActionBar);
}
boolean useRedTheme = preferences.getBoolean(PREF_RED_THEME, false);
if (useRedTheme) {
setTheme(R.style.AppTheme_Red_NoActionBar);
}
boolean useYellowTheme = preferences.getBoolean(PREF_YELLOW_THEME, false);
if (useYellowTheme) {
setTheme(R.style.AppTheme_Yellow_NoActionBar);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bowler_profile_view);
Intent intent = getIntent();
Boolean shouldUpdate = getIntent().getExtras().getBoolean("shouldUpdate");
String savedLeagueId = intent.getStringExtra("leagueId");
String savedBowlerId = String.valueOf(getIntent().getIntExtra("bowlerId",2));
int bowlerId = Integer.valueOf(savedBowlerId);
getBowlerProfile(savedLeagueId, bowlerId);
// Get The min and max score
MaxMin bowlerMaxMin = db.getMaxAndminScoresAll();
Log.d("SCORES",
"\n\tMaximum Score is " + String.valueOf(bowlerMaxMin.getMax()) +
"\n\tMinimum Score is " + String.valueOf(bowlerMaxMin.getMin()));
}
public void getBowlerProfile(String savedLeagueId, int savedBowlerId) {
String bn, ba, bh;
SQLiteOpenHelper database = new DatabaseHelper(this);
SQLiteDatabase db = database.getReadableDatabase();
Cursor viewBowlerProfile = db.query( Bowler.TABLE_NAME,
new String[]{Bowler.COLUMN_ID, Bowler.COLUMN_LEAGUE_ID, Bowler.COLUMN_NAME, Bowler.COLUMN_BOWLER_AVERAGE, Bowler.COLUMN_BOWLER_HANDICAP, Bowler.COLUMN_TIMESTAMP},
Bowler.COLUMN_ID + "=?",
new String[]{String.valueOf(savedBowlerId)}, null, null, null, null);
if (viewBowlerProfile.moveToFirst()) {
//Prepare League Object
bowler = new Bowler(
viewBowlerProfile.getInt(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_ID)),
viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_LEAGUE_ID)),
bn = viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_NAME)),
ba = viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_BOWLER_AVERAGE)),
bh = viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_BOWLER_HANDICAP)),
viewBowlerProfile.getString(viewBowlerProfile.getColumnIndex(Bowler.COLUMN_TIMESTAMP)));
final TextView bowlerName = (TextView) findViewById(R.id.tvBowlerName);
final TextView bowlerAverage = (TextView) findViewById(R.id.tvBowlerAverageValue);
final TextView bowlerHandicap = (TextView) findViewById(R.id.tvBowlerHandicapValue);
bowlerName.setText(String.valueOf(bn));
bowlerAverage.setText(String.valueOf(ba));
bowlerHandicap.setText(String.valueOf(bh));
//Close Database Connection
viewBowlerProfile.close();
}
//View League Profile Cancel Button
final Button cancel_button = (Button) findViewById(R.id.bCancel);
cancel_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d("SAVEDLEAGUEID_VAL", ">>" + String.valueOf(savedLeagueId) + "<<");
Intent intent = new Intent(getApplicationContext(), BowlerActivity.class);
intent.putExtra("leagueId", savedLeagueId);
startActivity(intent);
finish();
overridePendingTransition(0, 0);
/*Intent intent = new Intent(getApplicationContext(), BowlerActivity.class);
intent.putExtra("leagueId", savedLeagueId);
Log.d("LEAGUEID VALUE","value of leagueId = " + String.valueOf(savedLeagueId));
startActivity(intent);
finish();
overridePendingTransition(0, 0);*/
}
});
//Edit League Profile Cancel Button
final Button edit_button = (Button) findViewById(R.id.bEdit);
edit_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int bowlerId = bowler.getId();
Intent intent = new Intent(getApplicationContext(), BowlerProfileEditActivity.class);
intent.putExtra("bowlerId", bowlerId);
intent.putExtra("leagueId", savedLeagueId);
startActivity(intent);
finish();
overridePendingTransition(0, 0);
}
});
}
}
Logcat
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'ca.rvogl.tpbcui.utils.MaxMin ca.rvogl.tpbcui.database.DatabaseHelper.getMaxAndminScoresAll()' on a null object reference
at ca.rvogl.tpbcui.views.BowlerProfileViewActivity.onCreate(BowlerProfileViewActivity.java:79)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
Attempting to group by bowlerId and seriesId
public Cursor getMaxMinScoresAllAndroid(String bowlerId) {
SQLiteDatabase db = this.getWritableDatabase();
String tmptbl = "summed_scores";
String tmptblcol = "sum_score";
String tmpBowlerIdCol = "bowler_id";
String tmpSeriesIdCol = "series_id";
String crttmptbl = "CREATE TEMP TABLE IF NOT EXISTS " + tmptbl + "(" +
tmptblcol + " INTEGER," +
tmpBowlerIdCol + " TEXT," +
tmpSeriesIdCol + " TEXT)";
String empttmptbl = "DELETE FROM " + tmptbl;
db.execSQL(crttmptbl);
db.execSQL(empttmptbl);
String[] columns = new String[]{"sum(score) AS "};
Cursor csr = db.query(Game.TABLE_NAME,columns,null,null,Game.COLUMN_BOWLER_ID + " = '" + bowlerId + "'", Game.COLUMN_SERIES_ID,null,null);
DatabaseUtils.dumpCursor(csr);
while (csr.moveToNext()) {
ContentValues cv = new ContentValues();
cv.put(tmptblcol,csr.getInt(csr.getColumnIndex(tmptblcol)));
cv.put(tmpBowlerIdCol,csr.getInt(csr.getColumnIndex(tmpBowlerIdCol)));
cv.put(tmpSeriesIdCol,csr.getInt(csr.getColumnIndex(tmpSeriesIdCol)));
db.insert(tmptbl,null,cv);
}
csr.close();
columns = new String[]{"max(" +
tmptblcol +
") AS " + DERIVEDCOL_MAXSCORE,
"min(" +
tmptblcol +
") AS " + DERIVEDCOl_MINSCORE};
return csr = db.query(tmptbl,columns,null,null,null,null,null);
}
public MaxMin getMaxAndminScoresAll(String bowlerId) {
MaxMin rv = new MaxMin(0,0);
Cursor csr = getMaxMinScoresAllAndroid(bowlerId);
if (csr.moveToFirst()) {
rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
}
csr.close();
return rv;
}
You could do this (assuming the table is named myscores and the columns are _id and score) using :-
WITH cte1 AS
(
sum(score) AS sum_score
FROM myscores
GROUP BY _id
)
SELECT max(sum_score) AS min_score, min(sum_score) FROM cte1;
Using this would result in the following :-
Notes
AS is used to rename the output columns
without renaming the columns they would be named max(sum_score) and min(sum_score) respectively.
SQL As Understood By SQLite - Aggregate Functions
This utilises the SQLite aggregate functions max and min and the GROUP BY clause to aggregate the columns according to the _id column.
This also utilises a Common Table Expression (an intermediate/temporary table).
SQL As Understood By SQLite - WITH clause
Incorporating into an Android App (see note at end)
The following is an example App demonstrates how this can be incorporated fro Android :-
First a simple class for the Minimum and maximum vales (as used in the alternative getMaxAndMinScores method)
MaxMin.java (optional)
public class MaxMin {
private int min;
private int max;
public MaxMin(int min, int max) {
this.min = min;
this.max = max;
}
public int getMin() {
return min;
}
public void setMin(int min) {
this.min = min;
}
public int getMax() {
return max;
}
public void setMax(int max) {
this.max = max;
}
}
DBHelper.java
The subclass of SQLiteOpenHelper (just the one table name myscores)
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TB_SCORE = "myscores";
public static final String COL_SCORE = "score";
public static final String COL_ID = BaseColumns._ID;
public static final String DERIVEDCOL_MAXSCORE = "max_score";
public static final String DERIVEDCOl_MINSCORE = "min_score";
private static final String crt_myscores_sql = "CREATE TABLE IF NOT EXISTS " + TB_SCORE + "(" +
COL_ID + " INTEGER," +
COL_SCORE + " INTEGER" +
")";
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(crt_myscores_sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
public long addScore(long id, int score) {
ContentValues cv = new ContentValues();
cv.put(COL_ID,id);
cv.put(COL_SCORE,score);
return this.getWritableDatabase().insert(TB_SCORE,null,cv);
}
public Cursor getMaxMinScores() {
String sum_score = "sum_score";
String cte1 = "cte1";
String rawqry = " WITH " + cte1 +
" AS " +
"(" +
"SELECT sum(" +
COL_SCORE +
") AS " + sum_score +
" FROM " + TB_SCORE + " GROUP BY " + COL_ID +
") " +
"SELECT " +
" max(" +
sum_score +
") AS " + DERIVEDCOL_MAXSCORE +
"," +
" min(" +
sum_score +
") AS " + DERIVEDCOl_MINSCORE +
" FROM " + cte1 + ";";
return this.getWritableDatabase().rawQuery(rawqry,null);
}
public MaxMin getMaxAndMinScores() {
MaxMin rv = new MaxMin(0,0);
Cursor csr = getMaxMinScores();
if (csr.moveToFirst()) {
rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
}
csr.close();
return rv;
}
}
MainActivity.java
The activity that a) adds some rows and then b) gets the maximum and minimum scores (twice using alternative methods) :-
public class MainActivity extends AppCompatActivity {
DBHelper mDBHlpr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHlpr = new DBHelper(this);
// Add Some scores
mDBHlpr.addScore(1,112);
mDBHlpr.addScore(1,123);
mDBHlpr.addScore(1,144);
mDBHlpr.addScore(2,212);
mDBHlpr.addScore(2,190);
mDBHlpr.addScore(2,300);
mDBHlpr.addScore(3,234);
mDBHlpr.addScore(3,134);
mDBHlpr.addScore(3,122);
mDBHlpr.addScore(4,100);
mDBHlpr.addScore(4,111);
mDBHlpr.addScore(4,114);
// Get The min and max scores example 1
Cursor csr = mDBHlpr.getMaxMinScores();
if (csr.moveToFirst()) {
int max_score = csr.getInt(csr.getColumnIndex(DBHelper.DERIVEDCOL_MAXSCORE));
int min_score = csr.getInt(csr.getColumnIndex(DBHelper.DERIVEDCOl_MINSCORE));
Log.d("SCORES",
"\n\tMaximum Score is " + String.valueOf(max_score) +
"\n\tMinimum Score is " + String.valueOf(min_score)
);
}
//Alternative utilising the MaxMin object
MaxMin mymaxmin = mDBHlpr.getMaxAndMinScores();
Log.d("SCORES",
"\n\tMaximum Score is " + String.valueOf(mymaxmin.getMax()) +
"\n\tMinimum Score is " + String.valueOf(mymaxmin.getMin())
);
}
}
IMPORTANT
The WITH clause was introduced in SQL 3.8.3, some older versions of Android (below lollipop (but can be device independent)) will not
support the WITH clause.
The following methods, as equivalents of getMaxMinScores and getMaxAndMinScores could be used for any Android version :-
public Cursor getMaxMinScoresAllAndroid() {
SQLiteDatabase db = this.getWritableDatabase();
String tmptbl = "summed_scores";
String tmptblcol = "sum_score";
String crttmptbl = "CREATE TEMP TABLE IF NOT EXISTS " + tmptbl + "(" +
tmptblcol + " INTEGER" +
")";
String empttmptbl = "DELETE FROM " + tmptbl;
db.execSQL(crttmptbl);
db.execSQL(empttmptbl);
String[] columns = new String[]{"sum(score) AS " + tmptblcol};
Cursor csr = db.query(TB_SCORE,columns,null,null,COL_ID,null,null);
DatabaseUtils.dumpCursor(csr);
while (csr.moveToNext()) {
ContentValues cv = new ContentValues();
cv.put(tmptblcol,csr.getInt(csr.getColumnIndex(tmptblcol)));
db.insert(tmptbl,null,cv);
}
csr.close();
columns = new String[]{"max(" +
tmptblcol +
") AS " + DERIVEDCOL_MAXSCORE,
"min(" +
tmptblcol +
") AS " + DERIVEDCOl_MINSCORE};
return csr = db.query(tmptbl,columns,null,null,null,null,null);
}
public MaxMin getMaxAndminScoresAllAndroid() {
MaxMin rv = new MaxMin(0,0);
Cursor csr = getMaxMinScoresAllAndroid();
if (csr.moveToFirst()) {
rv.setMin(csr.getInt(csr.getColumnIndex(DERIVEDCOl_MINSCORE)));
rv.setMax(csr.getInt(csr.getColumnIndex(DERIVEDCOL_MAXSCORE)));
}
csr.close();
return rv;
}
These utilise an intermediate temporary table so bypass the restriction of using WITH

Why is this SQLite database not working

I am trying to add a top 10 high scores to my game. The high scores are made of only two things - the score and the difficulty, but so far I don't understand very much how this database works but after several tutorials I have this done
public class DBHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "highscores";
private static final String TABLE_DETAIL = "scores";
private static final String KEY_ID = "id";
private static final String KEY_TIME = "time";
private static final String KEY_DIFFICULTY = "difficutly";
public DBHandler(Context context){ super(context, DATABASE_NAME, null, DATABASE_VERSION);}
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_HIGHSCORES_TABLE = "CREATE TABLE " + TABLE_DETAIL + "("
+ KEY_ID + " INTEGER PRIMARY KEY, "
+ KEY_TIME + " TEXT, "
+ KEY_DIFFICULTY + " TEXT)";
db.execSQL(CREATE_HIGHSCORES_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_DETAIL);
onCreate(db);
}
// Adding new score
public void addScore(int score) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_TIME, score); // score value
// Inserting Values
db.insert(TABLE_DETAIL, null, values);
db.close();
}
// Getting All Scores
public String[] getAllScores() {
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_DETAIL;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
int i = 0;
String[] data = new String[cursor.getCount()];
while (cursor.moveToNext()) {
data[i] = cursor.getString(1);
i = i++;
}
cursor.close();
db.close();
// return score array
return data;
}
}
And here is the class that I want to control the database from
public class highscores extends Activity {
private ListView scorebox;
#Override
protected void onCreate(Bundle savedInstanceState) {
DBHandler db = new DBHandler(this);
scorebox = (ListView) findViewById(R.id.scorebox);
super.onCreate(savedInstanceState);
setContentView(R.layout.highscores);
Log.d("Insert: ", "Inserting ..");
db.addScore(9000);
Log.d("Reading: ", "Reading all contacts..");
}
}
When I open the page with the high scores in the application - it is blank, how to make it display something, I tried with this command db.addScore(9000); but it doesn't work. Maybe I didn't told the database where to display that data ?
Edit the Highscore Class
public class highscores extends Activity {
private ListView scorebox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.highscores);
DBHandler db = new DBHandler(this);
scorebox = (ListView) findViewById(R.id.scorebox);
Log.d("Insert: ", "Inserting ..");
db.addScore(9000);
Log.d("Reading: ", "Reading all contacts..");
ArrayList<String>ar=new ArrayList<>();
ar=db.getAllScores();
ArrayAdapter<String>ar=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,s);
scorebox.setAdapter(ar);
}
}
Now in Your DBHandler class Edit getAllScores() method like this
public ArrayList getAllScores() {
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_DETAIL;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
ArrayList<String>data=new ArrayList<>();
while (cursor.moveToNext()) {
data.add(cursor.getString(1));
}
cursor.close();
db.close();
// return score array
return data;
}
if you are using emulator you can pull the db file and check if the table is created or not, if you are using a device you can use this command
cd /D D:\Android\SDK\platform-tools // android sdk path
adb -d shell
run-as com.pkg.pkgname
cat /data/data/com.pkg.pkgname/databases/highscores >/sdcard/highscores
it will copy your db file to device sd card. Using Sqlite browser you can open the db file and check the table is created or not.
Also uninstall the app and install it again
Use this to list your score in your listview
public class highscores extends Activity {
private ListView scorebox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.highscores);
DBHandler db = new DBHandler(this);
scorebox = (ListView) findViewById(R.id.scorebox);
Log.d("Insert: ", "Inserting ..");
db.addScore(9000);
Log.d("Reading: ", "Reading all contacts..");
String []s=db.getAllScores();
ArrayAdapter<String>ar=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,s);
scorebox.setAdapter(ar);
}
}

Copy and display data from one sqlite table to another at runtime

I am trying to make an android application that allows the user to create a custom workout list from an already existing list of workouts. I decided to create an sqlite database to accomplish this task. In my database handler class "DBHandles.java" I have created and populated "Table_Workouts" with all the available workouts in the application. Also in "DBHandles.java" I have created another empty table "Table_User_List" for the purpose of holding specific entries from the "Table_Workouts" table that the user selects. "Table_User_List" needs to be populated at runtime.
public class DBhandles extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "Workouts.db";
public static final String TABLE_WORKOUTS = "Workouts";
public static final String TABLE_USER_LIST = "UserWorkouts";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_DESCRIPTION = "description";
public static final String COLUMN_LINK = "link";
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_WORKOUTS_TABLE = "CREATE TABLE " +
TABLE_WORKOUTS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_NAME + " TEXT,"
+ COLUMN_DESCRIPTION + " TEXT,"
+ COLUMN_LINK + " TEXT" + ")";
String CREATE_USER_TABLE ="CREATE TABLE " +
TABLE_USER_LIST + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_NAME + " TEXT,"
+ COLUMN_DESCRIPTION + " TEXT,"
+ COLUMN_LINK + " TEXT" + ")";
db.execSQL(CREATE_WORKOUTS_TABLE);
db.execSQL(CREATE_USER_TABLE);
db.execSQL("INSERT INTO " + TABLE_WORKOUTS + "(name, description, link) VALUES ('Shoulder Press', 'Shoulder PRess description', 'https://www.youtube.com/watch?v=qEwKCR5JCog')");
public void addWorkout(Workout workout) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(COLUMN_NAME, workout.getWorkoutName());
values.put(COLUMN_DESCRIPTION, workout.getDescription());
values.put(COLUMN_LINK, workout.getLink());
db.insert(TABLE_USER_LIST, null, values);
} catch (Exception e){
Log.d(TAG, "Error while trying to add");
}
finally{
db.endTransaction();
}
//db.close();
}
public Workout findWorkout(String Workoutname) {
String query = "SELECT * FROM " + TABLE_WORKOUTS
+ " WHERE " + COLUMN_NAME
+ " = \"" + Workoutname + "\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Workout workout = new Workout();
if (cursor.moveToFirst()) {
cursor.moveToFirst();
workout.setID(Integer.parseInt(cursor.getString(0)));
workout.setWorkoutName(cursor.getString(1));
workout.setDescription((cursor.getString(2)));
workout.setLink(cursor.getString(3));
cursor.close();
} else {
workout = null;
}
db.close();
return workout;
}
public boolean deleteWorkout(String Workoutname) {
boolean result = false;
String query = " SELECT * FROM " + TABLE_USER_LIST
+ " WHERE " + COLUMN_NAME
+ " = \"" + Workoutname + "\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
Workout workout = new Workout();
if (cursor.moveToFirst()) {
workout.setID(Integer.parseInt(cursor.getString(0)));
db.delete(TABLE_WORKOUTS, COLUMN_ID + " = ?",
new String[] { String.valueOf(workout.getID()) });
cursor.close();
result = true;
}
db.close();
return result;
}
public ArrayList getAllWorkoutNames (){
return genericGetSQL(TABLE_WORKOUTS, COLUMN_NAME);
}
public ArrayList genericGetSQL(String whichTable, String whichColumn){
ArrayList<String> wrkArray = new ArrayList<String>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(whichTable, new String[]{whichColumn}, null,null, null, null,null);
String fieldToAdd = null;
if(cursor.moveToFirst()){
while(cursor.isAfterLast()==false){
fieldToAdd = cursor.getString(0);
wrkArray.add(fieldToAdd);
cursor.moveToNext();
}
cursor.close();
}
return wrkArray;
}
As you can see I am returning an Arraylist from the DBHandles.class to display the name column of the "Table_Workouts" table. This ArrayList is accessed in my "DisplayAllWorkouts.java" class. The "DiplayAllWorkouts.java" class generates a tablerow for each entry in the "Table_Workouts" table and displays the name column to the user.
public class DisplayAllWorkouts extends AppCompatActivity implements YourListFrag.OnFragmentInteractionListener {
DBhandles db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.displayworkoutlist);
yourListFrag = new YourListFrag();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.LinLayDisplayYourList, yourListFrag, "ARG_PARAM1").
commit();
context = this;
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
TableRow rowHeader = new TableRow(context);
rowHeader.setBackgroundColor(Color.parseColor("#c0c0c0"));
rowHeader.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
String[] headerText = {"NAME ", " ADD "};
for (String c : headerText) {
TextView tv = new TextView(this);
tv.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT));
tv.setTextSize(18);
tv.setPadding(5, 5, 5, 5);
tv.setText(c);
rowHeader.addView(tv);
}
tableLayout.addView(rowHeader);
db = yourListFrag.getDb();//new DBhandles(this, null, null, 1);
final ArrayList<String> arrNames = db.getAllWorkoutNames();
final ArrayList<String> arrDesc = db.getAllWorkoutDescription();
final ArrayList<String> arrLink = db.getAllWorkoutsLink();
for (int i = 0; i < arrNames.size(); i++) {
TableRow row = new TableRow(this);
final CheckBox AddBox = new CheckBox(this);
AddBox.setText("ADD");
final TextView nametv = new TextView(this);
//final TextView desctv = new TextView(this);
//final TextView linktv = new TextView(this);
nametv.setTextSize(30);
// desctv.setTextSize(30);
nametv.setText(arrNames.get(i));
//desctv.setText(arrDesc.get(i));
//linktv.setText(arrLink.get(i));
text = nametv.getText().toString();
row.addView(nametv);
row.addView(AddBox);
AddBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
// if(AddBox.isChecked()){
Workout wrk = (db.findWorkout(text));
db.addWorkout(wrk);
yourListFrag.refresh();
// yourListFrag.refresh();
// yourListFrag.refresh(text);
// }
// else{
// db.deleteWorkout(text);
//yourListFrag.delete(nametv.getText().toString());
// yourListFrag.refresh();
// }
}
});
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(DisplayAllWorkouts.this, DisplaySingleWorkout.class);
i.putExtra("itemName", nametv.getText());
i.putStringArrayListExtra("everydesc", arrDesc);
i.putStringArrayListExtra("everyname", arrNames);
i.putStringArrayListExtra("everylink",arrLink);
startActivity(i);
}
});
tableLayout.addView(row);
}
}
#Override
public void onFragmentInteraction(int position) {
}
}
My problem is as follows. I want to be able to click on a table row displayed in the "DisplayAllWorkouts.java" class and have the corresponding row in "Table_Workouts" table be copied to the "Table_User_List" table. Once the row is copied I want the name column of "Table_User_List" displayed in "YourListFrag.java" class and inflated in the "DisplayAllWorkouts.java" class.
public class YourListFrag extends Fragment {
private ArrayAdapter<String> arrayAdapter;
private ListView lstView;
public ArrayList<String> holdNamesFromDB;
final DBhandles db = new DBhandles(getContext(), null, null, 1);
public DBhandles getDb(){
return this.db;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_list, container, false);
lstView = (ListView)rootView.findViewById(R.id.lstView);
holdNamesFromDB = db.getAllUserWorkouts();
arrayAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, holdNamesFromDB);
lstView.setAdapter(arrayAdapter);
public void refresh(){//String text){
//arrayAdapter.add(text);
// db.getAllUserWorkouts();
// arrayAdapter.notifyDataSetChanged();
holdNamesFromDB = db.getAllUserWorkouts();
//arrayAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, db.getAllUserWorkouts());
arrayAdapter.notifyDataSetChanged();
// arrayAdapter.notifyDataSetChanged();
//
}
I need the fragment to refresh its view everytime a new entry is added to the "Table_User_List" so the user can see every entry of the name column of "Table_User_List" in real time. I put logs in my program and the the flow seemed to successfully reach all the appropriate method calls without throwing an error or crashing. However, my program does not display the entries from Table_User_List in the "YourListFrag.java" class. I don't know if their is a problem copying the row from one sqlite table to the other, displaying and refershing the name column in the fragment or inflating the fragment into "DisplayAllWorkouts.java" class. I have been struggling with this problem for awhile now and I finally decided to reach out to the community that has always been there for me. I have referenced the following sqlite copy data from one table to another
and i can't tell if this approach actually works in my program because nothing is displayed in the fragment. Thank you for your time and effort. I apologize for the lines of code i commented out and posted. I have been trying everything i could think of.

Listview isn't updating in Fragment

I know for sure that the updateFromDatabase() function works, I've used print statements to see that the entries put into mCoordinatesArray are there and not empty strings. However when I restart the app, the fragment never populates the list view with items in the database. I think it has something to do with the Fragment Lifecycle, but I have no idea.
Additionally, when I don't restart the app and run it for the first time the list view runs fine. When I rotate or restart the app, the list view no longer populates.
public class LocalFragment extends Fragment{
private ListView mLocalList;
private ArrayAdapter<String> adapter;
private ArrayList<String> mCoordinatesArray;
private BroadcastReceiver mBroadcastReceiver;
private LocationBaseHelper mDatabase;
private DateFormat dateFormat;
private String dateString;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.fragment_local,container,false);
// SQLite Setup
mDatabase = new LocationBaseHelper(getActivity());
mLocalList = (ListView) v.findViewById(R.id.lv_local);
mCoordinatesArray = new ArrayList<>();
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mCoordinatesArray);
if(!mDatabase.size().equals("0")){
updateFromDatabase();
}
mLocalList.setAdapter(adapter);
return v;
}
#Override
public void onResume() {
super.onResume();
if(mBroadcastReceiver == null){
mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
dateFormat = new SimpleDateFormat("MM/dd HH:mm:ss a");
dateString = dateFormat.format(new Date());
String[] data = intent.getStringExtra("coordinates").split(" ");
mDatabase.insertEntry(dateString,data[0],data[1]);
System.out.println(mDatabase.size());
mCoordinatesArray.add(dateString + " " + data[0] + " " + data[1]);
adapter.notifyDataSetChanged();
}
};
}
getActivity().registerReceiver(mBroadcastReceiver, new IntentFilter("location_update"));
}
#Override
public void onDestroy() {
super.onDestroy();
if(mBroadcastReceiver!=null){
getActivity().unregisterReceiver(mBroadcastReceiver);
}
}
// THIS METHOD CAN BE USED TO UPDATE THE ARRAY HOLDING COORDINATES FROM THE LOCAL DATABASE
private void updateFromDatabase(){
//mCoordinatesArray.clear();
mCoordinatesArray = mDatabase.getEntireDatabase();
adapter.notifyDataSetChanged();
}
}
Here's my Helper class, just in case, but I don't think the problem is here.
public class LocationBaseHelper extends SQLiteOpenHelper {
private static final int VERSION = 1;
private static final String D​A​T​A​B​A​S​E​_​N​A​M​E​ = "locationBase.db";
public LocationBaseHelper(Context context) {
super(context, D​A​T​A​B​A​S​E​_​N​A​M​E​, null, VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + LocationTable.NAME + " (" +
LocationTable.Cols.DATE_TIME + " text, " +
LocationTable.Cols.LATITUDE + " text, " +
LocationTable.Cols.LONGITUDE + " text )"
);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void insertEntry(String date_time, String latitude, String longitude){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues content = new ContentValues();
content.put(LocationTable.Cols.DATE_TIME,date_time);
content.put(LocationTable.Cols.LATITUDE,latitude);
content.put(LocationTable.Cols.LONGITUDE,longitude);
db.insert(LocationTable.NAME,null,content);
}
public ArrayList<String> getEntireDatabase(){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + LocationTable.NAME,null);
cursor.moveToFirst();
ArrayList<String> values = new ArrayList<>();
do{
String value = (String) cursor.getString(cursor.getColumnIndex(LocationTable.Cols.DATE_TIME)) + " " +
(String) cursor.getString(cursor.getColumnIndex(LocationTable.Cols.LATITUDE)) + " " +
(String) cursor.getString(cursor.getColumnIndex(LocationTable.Cols.LONGITUDE));
values.add(0,value);
}while(cursor.moveToNext());
return values;
}
public String size(){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM " + LocationTable.NAME,null);
cursor.moveToFirst();
return cursor.getString(0);
}
}
By calling mCoordinatesArray = mDatabase.getEntireDatabase(); you are changing the reference of mCoordinatesArray, and adapter is still holding the old reference, so it does not see any changes.
Instead of creating new instance of mCoordinateArray, you should rather just update values it contains, something like:
mCoordinateArray.clear();
mCoordinateArray.addAll(mDatabase.getData());
adapter.notifyDataSetChange();
That way you are changing the data that is referenced by adapter, instead of creating completely new set of data which the adapter is not aware of.
Try to recreate your ArrayAdapter instead of using .notifyDataSetChanged():
// update Data
mCoordinatesArray = mDatabase.getEntireDatabase();
// create new adapter with new updated array
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mCoordinatesArray);
// set adapter for the listview
mLocalList.setAdapter(adapter);
You can put this method in your fragment and call from activity that attach to fragment.
public void updateList(List<?> result) {
if (multimediaListRent.size()>0) {
multimediaGridView.setAdapter(gridMediaListAdapter);
multimediaListRent.clear();
}
gridMediaListAdapter.notifyDataSetChanged();
}

cursor.moveToFirst seems to be skipped

I'm new to Java and just tried to make a database. I managed to make a DB and all but when I want to read the values it seems to get an error.
This is my code for my settings activity (which asks for setting values and add them in the DB on a specific ID)
public class Settings extends Activity{
Button Save;
static Switch SwitchCalculations;
public static String bool;
public static List<Integer> list_id = new ArrayList<Integer>();
public static List<String> list_idname = new ArrayList<String>();
public static List<String> list_kind = new ArrayList<String>();
public static List<String> list_value = new ArrayList<String>();
static Integer[] arr_id;
static String[] arr_idname;
static String[] arr_kind;
static String[] arr_value;
public static final String TAG = "Settings";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
Save = (Button) findViewById(R.id.btnSave);
SwitchCalculations = (Switch) findViewById(R.id.switchCalcOnOff);
readData();
Save.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
writeData();
//Toast.makeText(this, "Data has been saved.", Toast.LENGTH_SHORT).show();
readData();
Save.setText("Opgeslagen");
}
});
}
public void writeData() {
int id = 1;
String idname = "switchCalcOnOff";
String kind = "switch";
boolean val = SwitchCalculations.isChecked();
String value = new Boolean(val).toString();
dbHelper_Settings dbh = new dbHelper_Settings(this);
SQLiteDatabase db = dbh.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(dbh.C_ID, id);
cv.put(dbh.C_IDNAME, idname);
cv.put(dbh.C_KIND, kind);
cv.put(dbh.C_VALUE, value);
if (dbh.C_ID.isEmpty() == true) {
db.insert(dbh.TABLE, null, cv);
Log.d(TAG, "Insert: Data has been saved.");
} else if (dbh.C_ID.isEmpty() == false) {
db.update(dbh.TABLE, cv, "n_id='1'", null);
Log.d(TAG, "Update: Data has been saved.");
} else {
Log.d(TAG, "gefaald");
}
db.close();
}
public void readData() {
dbHelper_Settings dbh = new dbHelper_Settings(this);
SQLiteDatabase db = dbh.getWritableDatabase();
List<String> list_value = new ArrayList<String>();
String[] arr_value;
list_value.clear();
Cursor cursor = db.rawQuery("SELECT " + dbh.C_VALUE + " FROM " + dbh.TABLE + ";", null);
if (cursor.moveToFirst()) {
do {
list_value.add(cursor.getString(0));
} while (cursor.moveToNext());
}
if (cursor != null && !cursor.isClosed()){
cursor.close();
}
db.close();
arr_value = new String[list_value.size()];
for (int i = 0; i < list_value.size(); i++){
arr_value[i] = list_value.get(i);
}
}
}
Then I have my dbHelper activity see below:
package com.amd.nutrixilium;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class dbHelper_Settings extends SQLiteOpenHelper{
private static final String TAG="dbHelper_Settings";
public static final String DB_NAME = "settings.db";
public static final int DB_VERSION = 10;
public final String TABLE = "settings";
public final String C_ID = "n_id"; // Special for id
public final String C_IDNAME = "n_idname";
public final String C_KIND = "n_kind";
public final String C_VALUE = "n_value";
Context context;
public dbHelper_Settings(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
}
// oncreate wordt maar 1malig uitgevoerd per user voor aanmaken van database
#Override
public void onCreate(SQLiteDatabase db) {
String sql = String.format("create table %s (%s int primary key, %s TEXT, %s TEXT, %s TEXT)", TABLE, C_ID, C_IDNAME, C_KIND, C_VALUE);
Log.d(TAG, "onCreate sql: " + sql);
db.execSQL(sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists " + TABLE); // wist een oudere database versie
Log.d(TAG, "onUpgrate dropped table " + TABLE);
this.onCreate(db);
}
}
And the weird thing is I don't get any error messages here.
But I used Log.d(TAG, text) to check where the script is being skipped and that is at cursor.moveToFirst().
So can anyone help me with this problem?
Here, contrary to what you seem to expect, you actually check that a text constant is not empty:
if (dbh.C_ID.isEmpty() == true) {
It isn't : it always contains "n_id"
I think your intent was to find a record with that id and, depending on the result, either insert or update.
You should do just that: attempt a select via the helper, then insert or update as in the code above.
Edit:
Add to your helper something like this:
public boolean someRowsExist(SQLiteDatabase db) {
Cursor cursor = db.rawQuery("select EXISTS ( select 1 from " + TABLE + " )", new String[] {});
cursor.moveToFirst();
boolean exists = (cursor.getInt(0) == 1);
cursor.close();
return exists;
}
And use it to check if you have any rows in the DB:
if (dbh.someRowsExist(db)) { // instead of (dbh.C_ID.isEmpty() == true) {
Looks like you're having trouble debugging your query. Android provides a handy method DatabaseUtils.dumpCursorToString() that formats the entire Cursor into a String. You can then output the dump to LogCat and see if any rows were actually skipped.

Categories

Resources