I have an input page which submits 4 strings into the helper. The helper is supposed to get the data and put it into the listView.
When I insert my data, the app doesnt crash but it leads me to the listview page with no rows inflated. The 4 data inputs are all strings and is submitted through a button. I'm not too sure what is wrong with my code. Would appreciate some advice :)
listview code
public class MyActivitiesPage extends AppCompatActivity {
private Cursor model = null;
private ListView list;
private dbHandler helper = null;
private activityAdapter adapter = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activities_page);
helper = new dbHandler(this);
list = findViewById(R.id.listView);
model = helper.getall();
adapter = new activityAdapter(this, model, 0);
list.setAdapter(adapter);
}
public static class activityHolder {
private TextView activitytext;
private TextView datetext;
private TextView timetext;
private TextView addresstext;
activityHolder(View row) {
activitytext = row.findViewById(R.id.activitytext);
datetext = row.findViewById(R.id.datetext);
timetext = row.findViewById(R.id.timetext);
addresstext = row.findViewById(R.id.addresstext);
}
void populateFrom(Cursor c, dbHandler helper){
activitytext.setText(helper.getActi(c));
datetext.setText(helper.getDate(c));
timetext.setText(helper.getTime(c));
addresstext.setText(helper.getAddr(c));
}
}
class activityAdapter extends CursorAdapter {
activityAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, flags);
}
public void bindView(View view, Context context, Cursor cursor) {
activityHolder holder = (activityHolder) view.getTag();
holder.populateFrom(cursor, helper);
}
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
activityHolder holder = new activityHolder(row);
row.setTag(holder);
return (row);
}
}
helper code
public class dbHandler extends SQLiteOpenHelper {
private Context context;
private static final String DATABASE_NAME = "handler.db";
private static final int SCHEMA_VERSION = 1;
public dbHandler(#Nullable Context context){
super(context, DATABASE_NAME, null, SCHEMA_VERSION);
this.context = context;
}
public void onCreate(SQLiteDatabase db) {
//Will be called ones when the database is not created
db.execSQL("CREATE TABLE dbTable ( _id INTEGER PRIMARY KEY AUTOINCREMENT, acti TEXT, date TEXT, time TEXT, addr TEXT );");
}
public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) {
//Will not be called upon until SCHEMA_VERSION increases
//For future upgrades
}
public Cursor getall() {
return (getReadableDatabase().rawQuery("SELECT * FROM dbTable", null));
}
public Cursor getById(String id) {
String[] args = {id};
return (getReadableDatabase().rawQuery("SELECT _id, acti, date, time, addr FROM dbTable WHERE _ID = ?", args));
}
public void insert(String acti, String date, String time, String addr) {
ContentValues cv = new ContentValues();
cv.put("acti", acti);
cv.put("date", date);
cv.put("time", time);
cv.put("addr", addr);
long result = getWritableDatabase().insert("dbTable", "firstvalue", cv);
if(result == -1){
Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "Added Successfully!", Toast.LENGTH_SHORT).show();
}
}
public void updateDetails(String id, String acti, String date, String time, String addr) {
ContentValues cv = new ContentValues();
String[] args = {id};
cv.put("acti", acti);
cv.put("date", date);
cv.put("time", time);
cv.put("addr", addr);
getWritableDatabase().update("dbTable", cv, " _ID = ?", args);
}
public String getID(Cursor c) { return (c.getString(0));}
public String getActi(Cursor c) { return (c.getString(1));}
public String getDate(Cursor c) { return (c.getString(2));}
public String getTime(Cursor c) { return (c.getString(3));}
public String getAddr(Cursor c) { return (c.getString(4));}
}```
Related
The app: I have an app that creates multiple machines with:
id, name and location
each of these machines I have to let the user input the income respectively.
The problem: I need to SUM all income(money, date, note, machines_id) inputted from each machine AND display it in a TextView in a different Activity.
My question: How do I get the data from the rawQuery of my getIncomeOfMachine method to another Activity?
What I tried: Using Bundles, Intents, SharedPreferences from the DBHelper class.
DBHelper
public class DBHelpter extends SQLiteOpenHelper {
private static final String DB_NAME = "machines.db";
private static final int DB_VERSION = 1;
public static final String TABLE_MACHINES = "machines";
public static final String MACHINES_COLUMN_NAME = "name";
public static final String MACHINES_COLUMN_LOCATION = "location";
public static final String MACHINES_ID = "id";
public static final String TABLE_INCOME = "income";
public static final String INCOME_COLUMN_MONEY = "money";
public static final String INCOME_COLUMN_DATE = "date";
public static final String INCOME_COLUMN_NOTE = "note";
public static final String INCOME_ID = "id";
public static final String INCOME_COLUMN_MACHINES_ID = "machines_id";
private Context mContext;
public DBHelpter(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String query1 = String.format("CREATE TABLE " + TABLE_MACHINES + "("
+ MACHINES_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ MACHINES_COLUMN_NAME + " TEXT NOT NULL, "
+ MACHINES_COLUMN_LOCATION + " TEXT NOT NULL)",
TABLE_MACHINES, MACHINES_COLUMN_NAME, MACHINES_COLUMN_LOCATION, MACHINES_ID);
String query2 = String.format("CREATE TABLE " + TABLE_INCOME + "("
+ INCOME_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ INCOME_COLUMN_MONEY + " REAL NOT NULL, "
+ INCOME_COLUMN_DATE + " DATE NOT NULL, "
+ INCOME_COLUMN_NOTE + " TEXT NOT NULL, "
+ INCOME_COLUMN_MACHINES_ID + " INTEGER NOT NULL)",
TABLE_INCOME, INCOME_ID, INCOME_COLUMN_MONEY, INCOME_COLUMN_DATE, INCOME_COLUMN_NOTE, INCOME_COLUMN_MACHINES_ID);
db.execSQL(query1);
db.execSQL(query2);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String query1 = String.format("DROP TABLE IF EXISTS " + TABLE_MACHINES);
String query2 = String.format("DROP TABLE IF EXISTS " + TABLE_INCOME);
db.execSQL(query1);
db.execSQL(query2);
onCreate(db);
}
public void insertNewMachine(String name, String location){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(MACHINES_COLUMN_NAME, name);
values.put(MACHINES_COLUMN_LOCATION, location);
db.insertWithOnConflict(TABLE_MACHINES, null, values, SQLiteDatabase.CONFLICT_REPLACE);
db.close();
}
public void insertNewIncome(Double money, String date, String note, long machines_id){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(INCOME_COLUMN_MONEY, money);
values.put(INCOME_COLUMN_DATE, date);
values.put(INCOME_COLUMN_NOTE, note);
values.put(INCOME_COLUMN_MACHINES_ID, machines_id);
db.insertWithOnConflict(TABLE_INCOME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
db.close();
}
public void getIncomeOfMachine(long machinesId){
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT machines_id, SUM(money) AS total FROM income WHERE machines_id = "+machinesId+"", null);
while (cursor.moveToFirst()){
String totalAmount = String.valueOf(cursor.getInt(0));
SharedPreferences mSharedPreferences = mContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor mEditor = mSharedPreferences.edit();
mEditor.putString("total_amount", totalAmount);
mEditor.commit();
}
cursor.close();
db.close();
}
public ArrayList<MachinesClass> getAllMachines(){
ArrayList<MachinesClass> machinesList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM "+ TABLE_MACHINES, null);
while (cursor.moveToNext()){
final long id = cursor.getLong(cursor.getColumnIndex(MACHINES_ID));
final String name = cursor.getString(cursor.getColumnIndex(MACHINES_COLUMN_NAME));
final String location = cursor.getString(cursor.getColumnIndex(MACHINES_COLUMN_LOCATION));
machinesList.add(new MachinesClass(id, name, location));
}
cursor.close();
db.close();
return machinesList;
}
RecyclerViewAdapter
public class MachinesAdapter extends RecyclerView.Adapter<MachinesAdapter.ViewHolder> {
private ArrayList<MachinesClass> machinesList;
private LayoutInflater mInflater;
private DBHelpter mDBHelpter;
private Context mContext;
public static final String PREFS_NAME = "MyPrefsFile";
public MachinesAdapter(Context mContext, ArrayList<MachinesClass> machinesList){
this.mContext = mContext;
this.machinesList = machinesList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.machines_list, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.mLocation.setText(machinesList.get(position).getLocation());
holder.v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences mSharedPreferences = mContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor mEditor = mSharedPreferences.edit();
mEditor.putString("location", machinesList.get(position).getLocation());
mEditor.putLong("machines_id", machinesList.get(position).getId());
mEditor.commit();
Bundle bundle = new Bundle();
bundle.putString("location", machinesList.get(position).getLocation());
Intent intent = new Intent(v.getContext(), MachineInfo.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtras(bundle);
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return machinesList != null ? machinesList.size() : 0;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView mLocation, mMoney;
public LinearLayout mLinearLayout;
public View v;
public ViewHolder(View v) {
super(v);
mLinearLayout = (LinearLayout) v.findViewById(R.id.linearLayout);
mLocation = (TextView) v.findViewById(R.id.tvLocation);
mMoney = (TextView) v.findViewById(R.id.tvMoney);
this.v = v;
}
}
}
MachineInfo
public class MachineInfo extends AppCompatActivity {
private TextView mLocation, mMoney, mNotes;
private DBHelpter mDBHelpter;
private FloatingActionButton mFAB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_machine_info);
mDBHelpter = new DBHelpter(getApplicationContext());
mLocation = (TextView) findViewById(R.id.tvLocation);
mMoney = (TextView) findViewById(R.id.tvMoney);
mNotes = (TextView) findViewById(R.id.tvNotes);
mFAB = (FloatingActionButton) findViewById(R.id.fabAddIncome);
SharedPreferences mSharedPreferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
String total_amount = mSharedPreferences.getString("total_amount", null);
mMoney.setText(total_amount);
String location = mSharedPreferences.getString("location", null);
mLocation.setText(location);
mFAB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(), IncomeCreation.class);
startActivity(i);
}
});
}
}
If you need any other Activity or layout, let me know!
First, I suggest a change to getIncomeOfMachine(). Since this method is in DBHelper, it should only be responsible for interacting with the database. It should not know anything about SharedPreferences or Activity. Instead, it should return the value retrieved from the database and let the caller decide what to do with that value. Since you know there is only one row in the resulting Cursor, you do not need a loop. Just move to the first row, get the total, and return it.
Second, since you are only passing a single value to an activity, and you presumably do not need to store it permanently for later use, you should use an Intent rather than SharedPreferences. Starting Another Activity has a clear example of sending a value to another activity. If you have problems using this example in your app, feel free to post a new question showing what you did and explaining the problem you encountered.
Thanks in advance for helping me out. This is my first time working on SQLite Database as well as creating an app.
Problem: When I click save"ImageButton" on the AddEntry.xml for some reason its not displaying on my listview which is located in my Fragment Home.xml. I found fragments to be a tad difficult since you have to change the code around in order for it to work. so please excuse if my code is all over the place.
AddEntry.java
public class AddEntry extends Fragment implements View.OnClickListener
{
EditText DescriptionET,CalorieET;
ImageButton Savebtn, Cancelbtn;
String description , calorieAmt;
CalorieDatabase calorieDB;
public AddEntry() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View myView = inflater.inflate(R.layout.fragment_add_entry,
container, false);
Savebtn = (ImageButton) myView.findViewById(R.id.SaveBtn);
Savebtn.setOnClickListener(this);
Cancelbtn = (ImageButton) myView.findViewById(R.id.CancelBtn);
Cancelbtn.setOnClickListener(this);
return myView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
DescriptionET= (EditText)view.findViewById(R.id.foodEditText);
CalorieET=(EditText)view.findViewById(R.id.caloriesEditText);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.SaveBtn:
description = DescriptionET.getText().toString();
calorieAmt=CalorieET.getText().toString();
((appMain) getActivity()).loadSelection(0);
break;
case R.id.CancelBtn:
EditText descriptionET=
(EditText)getView().findViewById(R.id.foodEditText);
descriptionET.setText("");
EditText calorieET=
(EditText)getView().findViewById(R.id.caloriesEditText);
calorieET.setText("");
break;
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onDetach() {
super.onDetach();
}
}
FragmentHome.java
public class FragmentHome extends Fragment implements
View.OnClickListener {
public static final String ARG_SECTION_NUMBER =
"section_number";
public static final String ARG_ID = "_id";
private TextView label;
private int sectionNumber = 0;
private Calendar fragmentDate;
ListView listview;
ImageButton AddEntrybtn;
CalorieDatabase calorieDB;
private View v;
private android.support.v4.app.FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
public FragmentHome() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.fragment_home,
container, false);
label= (TextView) myView.findViewById(R.id.section_label);
AddEntrybtn = (ImageButton) myView.findViewById(R.id.AddItems);
AddEntrybtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
((appMain)getActivity()).loadSelection(1);
}
});
return myView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle username = getActivity().getIntent().getExtras();
String username1 = username.getString("Username");
TextView userMain= (TextView)
getView().findViewById(R.id.User);
userMain.setText(username1);
openDataBase();
}
private void openDataBase (){
calorieDB= new CalorieDatabase(getActivity());
calorieDB.open();
}
private void closeDataBase(){
calorieDB.close();
};
private void populateLVFromDB(){
Cursor cursor = calorieDB.getAllRows();
String[] fromFieldNames = new String[]
{CalorieDatabase.KEY_NAME, CalorieDatabase.KEY_CalorieValue};
int[] toViewIDs = new int[]
{R.id.foodEditText, R.id.caloriesEditText, };
SimpleCursorAdapter myCursorAdapter =
new SimpleCursorAdapter(
getActivity(),
R.layout.row_item,
cursor,
fromFieldNames,
toViewIDs
);
// Set the adapter for the list view
listview = (ListView) getActivity().findViewById(R.id.listViewDB);
listview.setAdapter(myCursorAdapter);
}
#Override
public void onResume() {
super.onResume();
// set label to selected date. Get date from Bundle.
int dayOffset = sectionNumber -
FragmentHomeDayViewPager.pagerPageToday;
fragmentDate = Calendar.getInstance();
fragmentDate.add(Calendar.DATE, dayOffset);
SimpleDateFormat sdf = new
SimpleDateFormat(appMain.dateFormat);
String labelText = sdf.format(fragmentDate.getTime());
switch (dayOffset) {
case 0:
labelText += " (Today)";
break;
case 1:
labelText += " (Tomorrow)";
break;
case -1:
labelText += " (Yesterday)";
break;
}
label.setText(labelText);
}
#Override
public void onDestroy() {
super.onDestroy();
closeDataBase();
}
#Override
public void onDetach() {
super.onDetach();
startActivity( new Intent(getContext(),MainActivity.class));
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.AddItems:
AddEntry addEntry = new AddEntry();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.FragmentHolder,addEntry)
.commit();
break;
}
}
}
CalorieDatabase.java
public class CalorieDatabase {
// Constants & Data
private static final String TAG = "DBAdapter";
// DB Fields
public static final String KEY_ROWID = "_id";
public static final int COL_ROWID = 0;
public static final String KEY_NAME = "Description";
public static final String KEY_CalorieValue = "Calories";
public static final int COL_NAME = 1;
public static final int COL_CalorieValue= 2;
public static final String[] ALL_KEYS = new String[]
{KEY_ROWID, KEY_NAME, KEY_CalorieValue};
public static final String DATABASE_NAME = "CalorieDb";
public static final String DATABASE_TABLE = "Calorie_Info";
public static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_NAME + " text not null, "
+ KEY_CalorieValue + " integer not null "
+ ");";
private final Context context;
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
public CalorieDatabase(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public CalorieDatabase open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
// Add a new set of values to the database.
public long insertRow(String description, int CalorieVal) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, description);
initialValues.put(KEY_CalorieValue, CalorieVal);
// Insert it into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String description, int
CalorieValue) {
String where = KEY_ROWID + "=" + rowId;
ContentValues newValues = new ContentValues();
newValues.put(KEY_NAME, description);
newValues.put(KEY_CalorieValue, CalorieValue);
// Insert it into the database.
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int
newVersion) {
Log.w(TAG, "Upgrading application's database from version " +
oldVersion
+ " to " + newVersion + ", which will destroy all old
data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
// Recreate new database:
onCreate(_db);
}
}
}
Thanks again for helping me out. I've been stressing for the last couple of days trying to figure it out.
I am currently trying to add a deleting ability to a ListView onItemLongClick. Unfortunately, for some reason I cannot seem to do this. Whenever I long click, the dialog box appears correctly and when I press yes to delete, nothing at all happens. The item still remains in the Listview and in the database because I call the method to display all the items from the updated database right after I call my delete method. I have been trying to fix this problem for two days now and I have gotten nowhere. It seems as though it is unable to retrieve an Id from the database for each item, but I am not sure why it would be doing this.
Here is my habit object class:
public class Habit extends Object implements Serializable{
private int day_count;
private int _id;
private String habit_name, date_started, end_date, day_count_string, id_string;
public Habit(){
}
public Habit(int id, String name, String startDate, String endDate, int dayCount){
this._id = id;
this.habit_name = name;
this.date_started = startDate;
this.end_date = endDate;
this.day_count = dayCount;
}
public Habit(String name, String startDate, String endDate, int dayCount){
this.habit_name = name;
this.date_started = startDate;
this.end_date = endDate;
this.day_count = dayCount;
}
public int getID()
{
return _id;
}
public int setID(int id)
{
return this._id;
}
public String getIDString()
{
id_string = "" + this._id;
return id_string;
}
public int getDayCount()
{
return this.day_count;
}
public String getDayCountString()
{
day_count_string = "" + this.day_count;
return day_count_string;
}
public int setDayCount(int dayCount)
{
return this.day_count;
}
public String getName()
{
return this.habit_name;
}
public void setName(String name)
{
this.habit_name = name;
}
public String getStartDate()
{
return this.date_started;
}
public void setStartDate(String startDate)
{
this.date_started = startDate;
}
public String getEndDate()
{
return this.end_date;
}
public void setEndDate(String endDate)
{
this.end_date = endDate;
}
}
Here is my databaseHelper code where I call add habit to create one habit item in the database and I call deleteHabit to delete the habit at the location of the id that is in the habit object class:
public class HabitDbHelper extends SQLiteOpenHelper{
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME="habits";
public static final String TABLE_HABITS = "habit_names";
public static final String KEY_NAME = "hname";
public static final String KEY_ID = "id";
public static final String KEY_STARTDATE = "start_date";
public static final String KEY_ENDDATE = "end_date";
public static final String KEY_DAYCOUNT = "day_count";
public HabitDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+TABLE_HABITS+" ("
+KEY_ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "
+KEY_NAME+" TEXT, "
+KEY_STARTDATE+" TEXT, "
+KEY_ENDDATE+" TEXT, "
+KEY_DAYCOUNT+" INTEGER);");
}
// Upgrading Database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_HABITS);
onCreate(db);
}
//Adding new habit
public void addHabit(Habit habit) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, habit.getName()); // Habit Name
values.put(KEY_STARTDATE, habit.getStartDate()); // Start Date
values.put(KEY_ENDDATE, habit.getEndDate()); // End Date
values.put(KEY_DAYCOUNT, habit.getDayCount());
// Inserting Row
db.insert(TABLE_HABITS, null, values);
db.close(); // Closing database connection
}
// Fetching 1 Habit
public Habit getHabit(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_HABITS, new String[] { KEY_ID,
KEY_NAME, KEY_STARTDATE ,KEY_ENDDATE, KEY_DAYCOUNT }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Habit habit = new Habit(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2), cursor.getString(3), Integer.parseInt(cursor.getString(4)));
// return contact
return habit;
}
// Fetching all Habits
public ArrayList<Habit> getAllHabits() {
ArrayList<Habit> habitList = new ArrayList<Habit>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_HABITS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Habit habit = new Habit();
habit.setID(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_ID))));
habit.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
habit.setStartDate(cursor.getString(cursor.getColumnIndex(KEY_STARTDATE)));
habit.setEndDate(cursor.getString(cursor.getColumnIndex(KEY_ENDDATE)));
habit.setDayCount(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_DAYCOUNT))));
// Adding contact to list
habitList.add(habit);
} while (cursor.moveToNext());
}
return habitList;
}
// Deleting Single Habit
public void deleteHabit(Habit habit) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_HABITS, KEY_ID + " = ?",
new String[] { String.valueOf(habit.getID()) });
db.close();
}
}
Here is my Listview adapter where each item is put into a custom item layout:
public class HabitAdapter extends BaseAdapter {
private ArrayList<Habit> habits;
private Context context;
private int layoutId;
private long id1;
public HabitAdapter(Context c, int LayoutId,ArrayList<Habit> habits) {
this.context = c;
this.layoutId = LayoutId;
this.habits = habits;
}
#Override
public int getCount() {
return habits.size();
}
#Override
public Habit getItem(int position) {
return habits.get(position);
}
#Override
public long getItemId(int position) {
Habit habit = (Habit)habits.get(position);
id1 = Long.parseLong(habit.getIDString());
return id1;
}
public View getView(int pos, View child, ViewGroup parent) {
Holder mHolder;
LayoutInflater layoutInflater;
Habit habit = habits.get(pos);
if (child == null) {
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.fragment_start_habit_item, null);
mHolder = new Holder();
mHolder.title = (TextView)child.findViewById(R.id.fragment_title);
mHolder.dayCount = (TextView)child.findViewById(R.id.fragment_days_left);
mHolder.startDate = (TextView)child.findViewById(R.id.fragment_start_date);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
mHolder.title.setText(habit.getName());
mHolder.dayCount.setText("Days Completed: " + habit.getDayCountString());
mHolder.startDate.setText("Date Started: " + habit.getStartDate());
return child;
}
public class Holder {
TextView title;
TextView dayCount;
TextView startDate;
}
}
And finally, my main activity where I delete the item that is selected onItemLongClick:
public class fourtyMain extends Activity
{
private HabitDbHelper mDB;
private ListView mList;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fourty_main);
mList = (ListView)findViewById(R.id.habit_list);
mDB = new HabitDbHelper(this);
getActionBar().setDisplayShowTitleEnabled(false);
//Start new activity with click
mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long arg3)
{
Intent singleI = new Intent(fourtyMain.this, SingleHabitView.class);
final Habit habit = (Habit) parent.getAdapter().getItem(position);
singleI.putExtra("habit", habit);
startActivity(singleI);
}
});
//long click to delete data
mList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, final View view, int position, long id) {
final Habit habit = (Habit) parent.getAdapter().getItem(position);
deleteHabitInListView(habit);
return true;
}
private void deleteHabitInListView(final Habit habit){
Builder deleteDialog = new AlertDialog.Builder(fourtyMain.this);
deleteDialog.setTitle("Delete " + habit.getName() + "?");
deleteDialog.setMessage("Are you sure you want to delete this habit? All your progress will be lost!");
deleteDialog.setPositiveButton("Yes", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
mDB.deleteHabit(habit);
displayData();
}
});
deleteDialog.setNegativeButton("No", new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
deleteDialog.show();
}
});
}
//Populate Listview
#Override
protected void onResume() {
displayData();
super.onResume();
}
private void displayData()
{
ArrayList<Habit> habitList = mDB.getAllHabits();
HabitAdapter disadpt = new HabitAdapter(fourtyMain.this, R.layout.fragment_start_habit_item, habitList);
mList.setAdapter(disadpt);
disadpt.notifyDataSetChanged();
}
}
I am absolutely lost on this one. I have been working for two days now to try and fix this problem and I have gotten nowhere. If I had to guess, I think I am going wrong on either retrieving the ID from the database or storing it incorrectly.
EDIT:
To add to this, I just found a way to write the id to a toast whenever the item is clicked. No matter what item in the list, it is returning 0 for the id. This makes me think that I am either fetching the id incorrectly or storing it incorrectly and my delete function is correct.
Insted of handling listview's setOnItemLongClickListener method, handl the perticuler cell's setOnItemLongClickListener
just like bleow :
public View getView(int pos, View child, ViewGroup parent) {
Holder mHolder;
LayoutInflater layoutInflater;
Habit habit = habits.get(pos);
if (child == null) {
layoutInflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.fragment_start_habit_item, null);
mHolder = new Holder();
mHolder.llCellLayout = (LinearLayout)child.findViewById(R.id.llCellLayout);
mHolder.title = (TextView)child.findViewById(R.id.fragment_title);
mHolder.dayCount = (TextView)child.findViewById(R.id.fragment_days_left);
mHolder.startDate = (TextView)child.findViewById(R.id.fragment_start_date);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
mHolder.title.setText(habit.getName());
mHolder.dayCount.setText("Days Completed: " + habit.getDayCountString());
mHolder.startDate.setText("Date Started: " + habit.getStartDate());
mHolder.llCellLayout.setOnItemLongClickListener(new OnItemLongClickListener(){
//** you can get id here and write code here for delete**
});
return child;
}
public class Holder {
TextView title;
TextView dayCount;
TextView startDate;
LinearLayout llCellLayout; //** this is the layout of cell**
}
try this code for delete operation
public float delete(String table,String colmName,String data) {
// TODO Auto-generated method stub
SQLiteDatabase db=dbhlpr.getWritableDatabase();
String[] arr={data};
colmName=colmName+"=?";
float res=db.delete(table, colmName,arr );
db.close();
return res;
}
Try to delete like below,
// Deleting Single Habit
public void deleteHabit(Habit habit) {
SQLiteDatabase database = this.getWritableDatabase();
{
database.execSQL("delete from " + "TABLE_HABITS"
+ " where KEY_ID='" + String.valueOf(habit.getID())+ "'");
}
database .close();
}
you could try the following:
1.Either change the query to a raw query like this:
public void deleteHabit(Habit habit) {
SQLiteDatabase db = this.getWritableDatabase();
String sql = "delete from " + TABLE_HABITS + " where "
+ KEY_ID + "=" + habit.getID();
db.rawQuery(sql,null);
db.close();
}
2.Or you could also try this:
public void deleteHabit(Habit habit) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_HABITS, KEY_ID+ "=" + habit.getID(), null);
db.close();
}
Hope that helps!
I managed to figure it out and of course it was the simplest error possible. In my habit object class I had it written:
public int setID(int id)
{
return this._id;
}
When all I needed to do was change it to this:
public void setID(int id)
{
this._id = id;
}
Stupid rookie mistake on my part but luckily thanks to trial and error by everybody I finally figured out my screw up. Thanks to anybody that helped out!
The delete method of my sql database doesn't remove the entry from the database. It gives a null pointer exception:
10-18 00:44:25.069: E/AndroidRuntime(17968): java.lang.NullPointerException
10-18 00:44:25.069: E/AndroidRuntime(17968): at com.weather.app.LocationDB.deleteLocation(LocationDB.java:98)
public class LocationDB extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "locationManager";
private static final String TABLE_LOCATIONS = "locations";
private static final String KEY_ID = "id";
private static final String KEY_LOCATION = "location";
private static final String KEY_COUNTRY = "country";
private SQLiteDatabase db;
public LocationDB(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_LOCATIONS + " ( "
+ KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_LOCATION
+ " TEXT, " + KEY_COUNTRY
+ " TEXT, " + " INTEGER)";
db.execSQL(sql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_LOCATIONS);
onCreate(db);
}
public void addLocation(LocationName location) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_LOCATION, location.getTaskName());
values.put(KEY_COUNTRY, location.getTaskCountry());
db.insert(TABLE_LOCATIONS, null, values);
}
public List<LocationName> getAllLocations() {
List<LocationName> locList = new ArrayList<LocationName>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_LOCATIONS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
LocationName task = new LocationName();
task.setId(cursor.getInt(0));
task.setTaskName(cursor.getString(1));
task.setTaskCountry(cursor.getString(2));
// Adding contact to list
locList.add(task);
} while (cursor.moveToNext());
}
return locList;
}
public boolean deleteLocation(long rowId) {
return db.delete(TABLE_LOCATIONS, KEY_ID + "=" + rowId, null) > 0;
}
}
Then entry is not removed even when the app is restarted, the addLocation method for adding a row works fine.
LocationSettings Activity:
public class LocationSettings extends Activity {
protected static LocationDB db;
static List<LocationName> list;
MyAdapter adapt;
private static TextView name;
private ListView listView;
private static final int DLG_EXAMPLE1 = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_settings);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
db = new LocationDB(this);
list = db.getAllTasks();
adapt = new MyAdapter(this, R.layout.drawer_list_item, list);
listView = (ListView) findViewById(R.id.left_drawer);
listView.setAdapter(adapt);
SwipeDismissListViewTouchListener touchListener =
new SwipeDismissListViewTouchListener(
listView,
new SwipeDismissListViewTouchListener.DismissCallbacks() {
#Override
public boolean canDismiss(int position) {
return true;
}
#Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
db.deleteTask(position);
adapt.remove(adapt.getItem(position));
}
}
});
listView.setOnItemClickListener(new DrawerItemClickListener());
listView.setOnTouchListener(touchListener);
}
public class DrawerItemClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
db.deleteTask(position);
adapt.notifyDataSetChanged();
}
}
private class MyAdapter extends ArrayAdapter<LocationName> {
Context context;
List<LocationName> taskList = new ArrayList<LocationName>();
int layoutResourceId;
public MyAdapter(Context context, int layoutResourceId,
List<LocationName> objects) {
super(context, layoutResourceId, objects);
this.layoutResourceId = layoutResourceId;
this.taskList = objects;
this.context = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.drawer_list_item,parent, false);
name = (TextView) convertView.findViewById(R.id.text1);
}
LocationName current = taskList.get(position);
name.setText(current.getTaskName());
return convertView;
}
}
}
you forget to initialize db before calling delete method in deleteLocation.
public int deleteLocation(long rowId) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TABLE_LOCATIONS, KEY_ID + " = ?",
new String[] { String.valueOf(rowId) });
}
Using the suggested following fragment of code from #ρяσѕρєяK:
public int deleteLocation(long rowId) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TABLE_LOCATIONS, KEY_ID + " = ?",
new String[] { String.valueOf(rowId) });
}
has changed the signature of your method generating that error. I think that
public boolean deleteLocation(long rowId) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TABLE_LOCATIONS, KEY_ID + " = ?",
new String[] { String.valueOf(rowId) }) > 0;
}
will solve your problem.
Im having trouble getting individual items to delete in a database my application is using. I know the method gets called, but nothing in my list is ever removed. Im not getting any errors which is making it tough to track down. Assistance would be awesome.
public class MainActivity extends Activity{
//Global Variables
ListView lv;
Intent addM, viewM;
public DBAdapter movieDatabase;
String tempTitle, tempYear;
int request_Code = 1;
int request_code2 = 2;
SimpleCursorAdapter dataAdapter;
Cursor cursor;
Button addButton;
long testID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//creates the database
movieDatabase = new DBAdapter(this);
movieDatabase.open();
//movieDatabase.deleteAllMovies();
//creates the intents to start the sub activities
addM = new Intent(this, AddMovie.class);
viewM = new Intent(this, MovieView.class);
}
//handles the return of the activity addMovie
public void onActivityResult(int requestCode, int resultCode,
Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK)
{
switch(requestCode)
{
case 1:
dbAddMovie(data.getStringExtra("title"),
data.getStringExtra("year"));
break;
case 2:
testID = data.getLongExtra("rowid", -1);
dMovie(testID);
break;
}
}
}
//adds item to the movie list
public void dbAddMovie(String mT, String mY)
{
movieDatabase.open();
movieDatabase.insertMovie(mT, mY);
Toast.makeText(this, "Movie: " + mT + " added to database",
Toast.LENGTH_SHORT).show();
}
//deletes an entry into the database
public void dMovie(long rowid)
{
//Toast.makeText(this, "Deleting: " + rowid,
Toast.LENGTH_SHORT).show();
movieDatabase.deleteMovie(rowid);
movieDatabase.getAllMovies();
}
//displays the database as a list
public void displayListView()
{
addButton = (Button) findViewById(R.id.add);
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivityForResult(addM, 1);
}
});
cursor = movieDatabase.getAllMovies();
//columns to use
String[] columns = new String[]
{
movieDatabase.KEY_TITLE,
};
//xml data to bind the data to
int[] to = new int[]
{
R.id.column2,
};
//adapter to display the database as a list
dataAdapter = new SimpleCursorAdapter(this,
R.layout.complexrow, cursor, columns, to, 0);
//gets the List view resource
lv = (ListView) findViewById(R.id.movielist);
//sets the list view to use the adapter
lv.setAdapter(dataAdapter);
//handles the list click events
lv.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View
v, int position,
long id) {
Cursor cursor = (Cursor)
parent.getItemAtPosition(position);
Bundle mDet = new Bundle();
mDet.putString("title",
cursor.getString(cursor.getColumnIndex(movieDatabase.KEY_TITLE)));
mDet.putString("year",
cursor.getString(cursor.getColumnIndex(movieDatabase.KEY_YEAR)));
mDet.putInt("rId", position);
viewM.putExtras(mDet);
startActivityForResult(viewM, 2);
}
});
//dataAdapter.notifyDataSetChanged();
}
public void onResume()
{
super.onResume();
displayListView();
}
}
and my coresponding dbadapter class
public class DBAdapter {
public static final String KEY_ROWID = "_id";
public static final String KEY_TITLE = "title";
public static final String KEY_YEAR = "year";
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "MovieListDB";
private static final String DATABASE_TABLE = "MoviesTable";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE = "create table MoviesTable (_id
integer primary key autoincrement, " +
"title text not null, year not null);";
private final Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
try{
db.execSQL(DATABASE_CREATE);
} catch (SQLException e)
{
e.printStackTrace();
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion +
"which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS MoviesTable");
onCreate(db);
}
}
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
public void close()
{
DBHelper.close();
}
public long insertMovie(String title, String year)
{
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_TITLE, title);
initialValues.put(KEY_YEAR, year);
return db.insert(DATABASE_TABLE, null, initialValues);
}
public boolean deleteMovie(long rowID)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "='" + rowID+"'", null ) >-1;
}
public Cursor getAllMovies()
{
return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
KEY_YEAR}, null, null, null, null, null);
}
public Cursor getMovie(long rowID) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
KEY_TITLE, KEY_YEAR}, KEY_ROWID + "=" + rowID, null, null, null, null, null);
if(mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
}
public boolean updateContact(long rowID, String title, String year)
{
ContentValues args = new ContentValues();
args.put(KEY_TITLE, title);
args.put(KEY_YEAR, year);
return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowID, null) > 0;
}
public void deleteAllMovies() {
int doneDelete = 0;
doneDelete = db.delete(DATABASE_TABLE, null, null);
}
}
You're using the position returned from your listview as the row id in your database. This won't necessarily match up with your autoincremented "_id" in your database. position is just what position in the list it is.
You might want to think about using movieDatabase.KEY_ROWID as the key for your intents. Right now I see a mix of "rowid", "rId", "_id", and KEY_ROWID. It would simplify thing to just use the same key everywhere when referring to the same thing.
It looks like you continuously add bundles to the viewM intent. Is that true? If that's not your intent, you should either create a new intent for each click, or remove the previous bundles first.
I'm assuming KEY_ROWID is actually the name of the column? Try the following:
public boolean deleteMovie(long rowID)
{
return db.delete(DATABASE_TABLE, KEY_ROWID + "=?", new String[] { String.valueOf(rowID) }) >-1;
}