lundi 10 août 2015

Android App: Trying to write different values from an object that is in an array to their own columns in SQLite database

I'm new to android, and I'm trying to build a basic workout app that keeps track of different things like the exercise done, the weight, the number of reps, as well as the body parts that you are working for that day. Right now I have 3 different activities, one where you choose the 3 parts of the body that you are training for the day, which has a button that will open the second activity and pass the body parts you selected as well as the time/date to that second activity as extras. On my second activity ("AddExerciseActivity"), I have 3 fields where you enter the exercise name, rep number, and weight, and 3 buttons, Next, Previous, and Done. When Next or Previous are clicked, it saves the info you entered, as well as the info that was passed along as an extra as a "Workout" object that is stored in an array of "Workouts" (not an arraylist, I know arraylist is better, but I am only trying to get it to work, as this is only my first app). When the "Done" button is clicked, I try and write each attribute of each object in the array to their own column in my database, and it opens my third activity, which will have a list of all the dates/times that a workout was done as a ListView, which is where I get the error

    08-10 21:14:26.027  23941-23941/com.example.tycen.myfittrackerr2 E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.tycen.myfittrackerr2, PID: 23941
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
        at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:394)
        at android.widget.ArrayAdapter.getView(ArrayAdapter.java:362)
        at android.widget.AbsListView.obtainView(AbsListView.java:2842)
        at android.widget.ListView.measureHeightOfChildren(ListView.java:1290)
        at android.widget.ListView.onMeasure(ListView.java:1202)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5802)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1835)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:725)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:616)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5802)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.support.v7.internal.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:124)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5802)
        at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:444)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5802)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5802)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1835)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:725)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:616)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5802)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2881)
        at android.view.View.measure(View.java:18425)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2237)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1295)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1537)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1180)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6558)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
        at android.view.Choreographer.doCallbacks(Choreographer.java:590)
        at android.view.Choreographer.doFrame(Choreographer.java:560)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:145)
        at android.app.ActivityThread.main(ActivityThread.java:5835)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)

I know this is because I am trying to convert something that isn't there into a string when I try and generate my array for my ListView, which means that the write to my database isn't working, if someone could help me find the problem that would be greatly appreciated, and if you need any more details just ask

    import android.content.Intent;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Spinner;
    import android.widget.TextView;
    import android.widget.Toast;

    public class AddExerciseActivity extends ActionBarActivity {

String workoutDate;
String training1;
String training2;
String training3;
int i;

EditText exerciseNameInput;
EditText exerciseWeightInput;
Spinner repSpinner;

Workout workout;
Workout[] workouts = new Workout[20];

MyDbHandler dbHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_exercise);

    dbHandler = new MyDbHandler(this, null, null, 1);
    exerciseNameInput = (EditText)findViewById(R.id.exerciseNameInput);
    exerciseWeightInput = (EditText)findViewById(R.id.exerciseWeightInput);
    repSpinner = (Spinner)findViewById(R.id.repSpinner);
    i = 0;

    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        workoutDate = extras.getString("workoutDate");
        training1 = extras.getString("training1");
        training2 = extras.getString("training2");
        training3 = extras.getString("training3");
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

public void nextButtonClicked(View view){

    workout = new Workout("","","","","",0,0);

    if(exerciseNameInput.getText().toString().matches("") || exerciseWeightInput.getText().toString().matches("")){
        Toast.makeText(this, "You must enter a value for both the Exercise and Weight fields", Toast.LENGTH_LONG).show();
        return;
    }

    workout.set_exercise(exerciseNameInput.getText().toString());
    workout.set_weight(Integer.parseInt(exerciseWeightInput.getText().toString()));
    workout.set_repNumber(repSpinner.getSelectedItemPosition());
    workout.set_date(workoutDate);
    workout.set_training1(training1);
    workout.set_training2(training2);
    workout.set_training3(training3);

    workouts[i] = workout;
    i++;

    if(workouts[i] == null) {
        exerciseNameInput.getText().clear();
        exerciseWeightInput.getText().clear();
        repSpinner.setSelection(0);
    }
    else{
        exerciseNameInput.setText(workouts[i].get_exercise(), TextView.BufferType.EDITABLE);
        exerciseWeightInput.setText(String.valueOf(workouts[i].get_weight()), TextView.BufferType.EDITABLE);
        repSpinner.setSelection(workouts[i].get_repNumber());
    }

    Toast.makeText(this, String.valueOf(i), Toast.LENGTH_LONG).show();

}

public void previousButtonClicked(View view){

    workout = new Workout("","","","","",0,0);

    if(i > 0){
        if(workouts[i] == null && exerciseWeightInput.getText() != null){
            workout.set_exercise(exerciseNameInput.getText().toString());
            workout.set_weight(Integer.parseInt(exerciseWeightInput.getText().toString()));
            workout.set_repNumber(repSpinner.getSelectedItemPosition());
            workout.set_date(workoutDate);
            workout.set_training1(training1);
            workout.set_training2(training2);
            workout.set_training3(training3);

            workouts[i] = workout;

            i--;

            exerciseNameInput.setText(workouts[i].get_exercise(), TextView.BufferType.EDITABLE);
            exerciseWeightInput.setText(String.valueOf(workouts[i].get_weight()), TextView.BufferType.EDITABLE);
            repSpinner.setSelection(workouts[i].get_repNumber());
        }
        else{

            if(!exerciseNameInput.getText().toString().equals(workouts[i].get_exercise()) ||
                    !exerciseWeightInput.getText().toString().equals(workouts[i].get_weight()) ||
                    repSpinner.getSelectedItemPosition() != workouts[i].get_repNumber()){

                workout.set_exercise(exerciseNameInput.getText().toString());
                workout.set_weight(Integer.parseInt(exerciseWeightInput.getText().toString()));
                workout.set_repNumber(repSpinner.getSelectedItemPosition());

                workouts[i] = workout;

                i--;

                exerciseNameInput.setText(workouts[i].get_exercise(), TextView.BufferType.EDITABLE);
                exerciseWeightInput.setText(String.valueOf(workouts[i].get_weight()), TextView.BufferType.EDITABLE);
                repSpinner.setSelection(workouts[i].get_repNumber());
            }
            else {
                i--;
                exerciseNameInput.setText(workouts[i].get_exercise(), TextView.BufferType.EDITABLE);
                exerciseWeightInput.setText(String.valueOf(workouts[i].get_weight()), TextView.BufferType.EDITABLE);
                repSpinner.setSelection(workouts[i].get_repNumber());
            }
        }
    }
    else{
        Toast.makeText(this, "You are at the beginning of your exercise list", Toast.LENGTH_LONG).show();
    }

}

public void doneButtonClicked(View view){

    if(workouts[i] == null){
        workout = new Workout("","","","","",0,0);

        workout.set_exercise(exerciseNameInput.getText().toString());
        workout.set_weight(Integer.parseInt(exerciseWeightInput.getText().toString()));
        workout.set_repNumber(repSpinner.getSelectedItemPosition());
        workout.set_date(workoutDate);
        workout.set_training1(training1);
        workout.set_training2(training2);
        workout.set_training3(training3);

        workouts[i] = workout;
    }

    dbHandler.addWorkout(workouts);
    Intent workoutsList = new Intent(this, PreviousWorkoutListActivity.class);
    startActivity(workoutsList);

}

}

my dbhandler

    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.database.Cursor;
    import android.content.Context;
    import android.content.ContentValues;
    import android.util.Log;
    import android.widget.Toast;


    public class MyDbHandler extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 2; //Consists of x (1) tables that can store as much data as needed
private static final String DATABASE_NAME = "workouts.db"; //database file name
public static final String TABLE_WORKOUTS = "workouts"; //table name
public static final String COLUMN_ID = "_id"; //column name of database table
public static final String COLUMN_WORKOUTDATE = "workoutDate"; //column name of database table
public static final String COLUMN_TRAINING1 = "training1"; //column name of database table
public static final String COLUMN_TRAINING2 = "training2"; //column name of database table
public static final String COLUMN_TRAINING3 = "training3"; //column name of database table
public static final String COLUMN_EXERCISENAME = "exerciseName";//column name of database table
public static final String COLUMN_WEIGHT = "weight";//column name of database table
public static final String COLUMN_REPS = "repNumber";//column name of database table

private static final String TAG = "MyActivity";

public MyDbHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
    super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}

@Override// when it creates database for very first time, this is what it does
public void onCreate(SQLiteDatabase db) {
    String query = "CREATE TABLE " + TABLE_WORKOUTS + "(" +
            COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + //id will be an integer, and is the primary key for the table
            COLUMN_WORKOUTDATE + " TEXT, " +
            COLUMN_TRAINING1 + " TEXT, " +
            COLUMN_TRAINING2 + " TEXT, " +
            COLUMN_TRAINING3 + " TEXT, " +
            COLUMN_EXERCISENAME + " TEXT, " +
            COLUMN_WEIGHT + " INTEGER, " +
            COLUMN_REPS + " TEXT " +
            ");";
    db.execSQL(query);// this is how you execute queries with android
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORKOUTS);
    onCreate(db);//because you need to create a new db
}

//Add a new row to the database
public void addWorkout(Workout[] workouts){//can extract information from "Products" object
    ContentValues values = new ContentValues();

    Log.v(TAG, workouts[0].get_exercise());

    int i = 0;

    SQLiteDatabase db = getWritableDatabase();// db is now equal to the database we are going to write to

    while(workouts[i] != null){

        values.clear();

        //GOING TO HAVE TO PASS IN ARRAY TO AND TRY AND WRITE VALUES TO DATABASE BASED ON ARRAY
        values.put(COLUMN_WORKOUTDATE, workouts[i].get_date());
        values.put(COLUMN_TRAINING1, workouts[i].get_training1());
        values.put(COLUMN_TRAINING2, workouts[i].get_training2());
        values.put(COLUMN_TRAINING3, workouts[i].get_training3());
        values.put(COLUMN_EXERCISENAME, workouts[i].get_exercise());
        values.put(COLUMN_WEIGHT, workouts[i].get_weight());
        values.put(COLUMN_REPS, workouts[i].get_repNumber());

        db.insert(TABLE_WORKOUTS, null, values);

        i++;
    }
    db.close();
}

//Delete a product from the database
public void deleteWorkout(){
    SQLiteDatabase db  = getWritableDatabase();
    db.execSQL("DROP TABLE IF EXISTS" + TABLE_WORKOUTS);
}

public String[] displayWorkoutInList(){

    //THIS SHOULD RETURN THE ARRAY THAT I CAN USE TO FILL IN THE TEXTFIELDS WHEN I DISPLAY THE VALUES

    String[] workoutDatesList = new String[20];
    int i = 0;
    boolean first = false;

    SQLiteDatabase db  = getWritableDatabase();
    String query = "SELECT * FROM " + TABLE_WORKOUTS + " WHERE 1"; //+ COLUMN_WORKOUTDATE + "=\"" + workoutDate + "\";";
    Cursor c = db.rawQuery(query, null);

    c.moveToFirst();

    while(!c.isAfterLast()){

        if(first == false){
            workoutDatesList[i] = c.getString(c.getColumnIndex("workoutDate"));
            first = true;
            i++;
        }
        else if(workoutDatesList[i - 1] != c.getString(c.getColumnIndex("workoutDate"))){
            workoutDatesList[i] = c.getString(c.getColumnIndex("workoutDate"));

            i++;
        }

        c.moveToNext();
    }

    db.close();

    return workoutDatesList;
}

//Print out the database as String for debugging
public void databaseToString(){
    String dbString = "";
    SQLiteDatabase db  = getWritableDatabase();
    String query = "SELECT * FROM " + TABLE_WORKOUTS + " WHERE 1"; //"WHERE 1" means select every row

    //Cursor points to location in my results
    Cursor c = db.rawQuery(query, null);
    //Move to the first row in your results
    c.moveToFirst();

    while(!c.isAfterLast()){// make sure you still have results
        if(c.getString(c.getColumnIndex("workoutDate")) != null){
            dbString += c.getString(c.getColumnIndex("workoutDate"));
            dbString += "\n";// put it on a new line
        }
        c.moveToNext();
    }
    db.close();
    Log.v(TAG, dbString);
}

}

and lastly my list of workouts excluding imports

    public class PreviousWorkoutListActivity extends ActionBarActivity{

MyDbHandler db;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_previous_workout_list);

    ListView prevWorkoutList = (ListView)findViewById(R.id.prevWorkoutsList);
    db = new MyDbHandler(this, null, null, 1);

    String[] list = db.displayWorkoutInList();
    ListAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);//can create my own list item to
                                                                                              //replace simple_list_item_1
    prevWorkoutList.setAdapter(adapter);

    prevWorkoutList.setOnItemClickListener(
            new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    //In here an activity will open that displays details for each exercise that was done in the workout
                    //much like the layout of AddExerciseActivity
                }
            }
    );
}

Aucun commentaire:

Enregistrer un commentaire