Im making an app where i download the data from an api. The data is downloaded every X minutes. When the data has been downloaded, it is stored in my DB. However, the problem i have is that whenever i update the db, the generateData() method in FragmentTrend crashes when i switch to another tab and comeback again. I get the the index out of bound exception as seen below. It crashes at line:
int y = Integer.parseInt(listDatastream.get(i).getCurrent_value());
Ive tried to test out that whenever the count != getNumberOfElementsInDatabase() then just return the value to see whether or not it would help, however, i end up with another error which is similar to this thread: DB error code 14
Any help would be appreciated! Ive been stuck with this problem for more than 3 days now! Thank you!
Additional information: I have 4 tabs and use FragmentStatePagerAdapter to navigate. Ive noticed one thing while navigating. Whenever i navigate to the neighboring tab (such as tab1 to tab2), the previous tab is not terminated. It is still on the run. I found this out by printing an endless forloop with text. The for loop stops only when im 2 tabs away (such as from tab1 to tab3 / tab4 or tab 2 to tab4 etc). So the app crashes only when i select tab3 or tab4 then reselect tab1 or tab2 respectively.
Error:
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: FATAL EXCEPTION: main
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: Process: com.thesis.dell.MaterialTest2, PID: 2618
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: java.lang.IndexOutOfBoundsException: Invalid index 166, size is 166
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at java.util.ArrayList.get(ArrayList.java:308)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at com.thesis.dell.MaterialTest2.fragments.FragmentTrend.generateData(FragmentTrend.java:166)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at com.thesis.dell.MaterialTest2.fragments.FragmentTrend.drawGraphVolt(FragmentTrend.java:112)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at com.thesis.dell.MaterialTest2.fragments.FragmentTrend.onCreateView(FragmentTrend.java:86)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at android.support.v4.app.Fragment.performCreateView(Fragment.java:1786)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)
10-29 19:37:09.693 2618-2618/? E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
FragmentTrend.java
package com.thesis.dell.MaterialTest2.fragments;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.LegendRenderer;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;
import com.thesis.dell.MaterialTest2.MyApplication;
import com.thesis.dell.MaterialTest2.R;
import com.thesis.dell.MaterialTest2.log.L;
import com.thesis.dell.MaterialTest2.pojo.Datastream;
import java.util.ArrayList;
public class FragmentTrend extends Fragment {
private static final String STATE_DATASTREAM2 = "state_datastream2";
private ArrayList<Datastream> listDatastream = new ArrayList<>();
//private SwipeRefreshLayout mSwipeRefreshLayout;
private View view;
private LineGraphSeries<DataPoint> mVolt;
private int count;
public FragmentTrend() {
// Required empty public constructor
}
public static FragmentTrend newInstance(String param1, String param2) {
FragmentTrend fragment = new FragmentTrend();
Bundle args = new Bundle();
//put any extra arguments that you may want to supply to this fragment
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.tab_trend,container,false);
count = getNumberOfElementsInDatabase();
//setupSwipe();
//printAllValuesInDatastream();
if (savedInstanceState != null) {
//if this fragment starts after a rotation or configuration change,
// load the existing data from a parcelable
L.t(getActivity(), "savedInstanceState not null");
listDatastream = savedInstanceState.getParcelableArrayList(STATE_DATASTREAM2);
}
else {
//if this fragment starts for the first time, load the list of data from a database
//get a reference to our DB running on our main thread
L.t(getActivity(), "savedInstanceState is null");
listDatastream = MyApplication.getWritableDatabase().readDatastreams();
}
if (listDatastream != null && !listDatastream.isEmpty()) {
drawGraphVolt();
}
return view;
}
public void drawGraphVolt () {
// Setting up and drawing volt graph
GraphView graph = (GraphView) view.findViewById(R.id.graph);
mVolt = new LineGraphSeries<>(generateData());
graph.addSeries(mVolt);
// styling grid/labels
graph.getGridLabelRenderer().setGridColor(getResources().getColor(R.color.colorGraphGrid));
graph.getGridLabelRenderer().setHorizontalLabelsColor(getResources().getColor(R.color.colorGraphText));
graph.getGridLabelRenderer().setVerticalLabelsColor(getResources().getColor(R.color.colorGraphText));
graph.getGridLabelRenderer().setTextSize(45);
graph.getGridLabelRenderer().reloadStyles();
// styling series
mVolt.setColor(getResources().getColor(R.color.colorAccent));
mVolt.setThickness(4);
//series.setDrawBackground(true);
//series.setBackgroundColor(getResources().getColor(R.color.gridGraphColor));
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().setMinY(graph.getViewport().getMinY(false));
graph.getViewport().setMaxY(graph.getViewport().getMaxY(false));
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(graph.getViewport().getMinX(true));
graph.getViewport().setMaxX(graph.getViewport().getMaxX(true));
mVolt.setTitle("Volt");
graph.getLegendRenderer().setVisible(true);
graph.getLegendRenderer().setAlign(LegendRenderer.LegendAlign.TOP);
graph.getLegendRenderer().setTextSize(45);
graph.getLegendRenderer().setBackgroundColor(getResources().getColor(R.color.colorPrimary));
graph.getLegendRenderer().setTextColor(getResources().getColor(R.color.colorPrimaryText));
graph.getLegendRenderer().setPadding(15);
graph.getLegendRenderer().setMargin(0);
graph.getViewport().setScrollable(true);
}
private DataPoint[] generateData() {
DataPoint[] values = new DataPoint[count];
for (int i = 0; i < count; i++) {
// if (count != getNumberOfElementsInDatabase()) {
//
// return values;
// }
int x = i;
int y = Integer.parseInt(listDatastream.get(i).getCurrent_value());
DataPoint v = new DataPoint(x, y);
values[i] = v
}
return values;
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(STATE_DATASTREAM2, listDatastream);
}
public int getNumberOfElementsInDatabase() {
int countListDatastream = MyApplication.getWritableDatabase().getTotalNumberOfElements();
return countListDatastream;
}
}
My Database:
package com.thesis.dell.MaterialTest2.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import com.thesis.dell.MaterialTest2.pojo.Datastream;
import com.thesis.dell.MaterialTest2.log.L;
import java.util.ArrayList;
import java.util.Date;
public class MyDatabase {
private MyHelper mHelper;
private SQLiteDatabase mDatabase;
public MyDatabase(Context context) {
mHelper = new MyHelper(context);
mDatabase = mHelper.getWritableDatabase();
//mDatabase.close();
}
public void insertValues(ArrayList<Datastream> listValues, boolean clearPrevious) {
if (clearPrevious) {
deleteData();
}
//beginTransaction(null /* transactionStatusCallback */, true); allowed to comment like this?
//create a sql prepared statement
String sql = "INSERT INTO " + MyHelper.TABLE_NAME + " VALUES (?,?,?);";
//compile the statement and start a transaction
SQLiteStatement statement = mDatabase.compileStatement(sql);
mDatabase.beginTransaction();
for (int i = 0; i < listValues.size(); i++) {
Datastream currentData = listValues.get(i);
statement.clearBindings();
//for a given column index, simply bind the data to be put inside that index
statement.bindString(2, currentData.getCurrent_value());
statement.bindLong(3, currentData.getCurrent_valueAt() == null ? -1 : currentData.getCurrent_valueAt().getTime());
L.m("Inserting entry " +i);
statement.execute();
}
//set the transaction as successful and end the transaction
mDatabase.setTransactionSuccessful();
mDatabase.endTransaction();
}
public int getTotalNumberOfElements() {
int numberOfElements = -1;
//get a list of columns to be retrieved, we need all of them
String[] columns = {MyHelper.COLUMN_VALUE, MyHelper.COLUMN_DATE_AT};
//make a simple query with dbname, columns and all other params as null
Cursor cursor = mDatabase.query(MyHelper.TABLE_NAME, columns, null, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
numberOfElements = cursor.getCount();
return numberOfElements;
}
return numberOfElements;
}
public ArrayList<Datastream> readDatastreams()
{
//init an empty array list
ArrayList<Datastream> listDatastream = new ArrayList<>();
//get a list of columns to be retrieved, we need all of them
String[] columns = {MyHelper.COLUMN_VALUE, MyHelper.COLUMN_DATE_AT};
//make a simple query with dbname, columns and all other params as null
Cursor cursor = mDatabase.query(MyHelper.TABLE_NAME, columns, null, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
do {
//create a new Datastream object and retrieve the data from the cursor to be stored in this Datastream object
Datastream datastream = new Datastream();
//each step is a 2 part process, find the index of the column first, find the data of that column using
//that index and finally set our blank Datastream object to contain our data
datastream.setCurrent_value(cursor.getString(cursor.getColumnIndex(MyHelper.COLUMN_VALUE)));
long valueAtMilliseconds = cursor.getLong(cursor.getColumnIndex(MyHelper.COLUMN_DATE_AT));
datastream.setCurrent_valueAt(valueAtMilliseconds != -1 ? new Date(valueAtMilliseconds) : null);
//add the datastream to the list of datastream objects which we plan to return
listDatastream.add(datastream);
}
while (cursor.moveToNext());
}
return listDatastream;
}
//delete all rows from our table
public void deleteData() {
mDatabase.delete(MyHelper.TABLE_NAME, null, null);
}
public long insertData(String value, String valueDate) {
SQLiteDatabase db = mHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(MyHelper.COLUMN_VALUE, value);
cv.put(MyHelper.COLUMN_DATE_AT, valueDate);
//ID indicates the row id that was inserted if successfull
long id = db.insert(MyHelper.TABLE_NAME, null, cv);
return id;
}
public String getColumnValueLast() {
SQLiteDatabase db = mHelper.getWritableDatabase();
String[] columns = {MyHelper.COLUMN_VALUE};
Cursor cursor = db.query(MyHelper.TABLE_NAME, columns, null, null, null, null, null );
String lastValue = "-1";
if (cursor.moveToLast()) {
int index1 = cursor.getColumnIndex(MyHelper.COLUMN_VALUE);
String value = cursor.getString(index1);
lastValue = value;
}
return lastValue;
}
static class MyHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "MyDB";
private static final String TABLE_NAME = "TableValue";
private static final int DB_VERSION = 2;
private static final String COLUMN_UID = "_id";
private static final String COLUMN_VALUE = "current_value";
private static final String COLUMN_DATE_AT = "at";
private static final String CREATE_TABLE = "CREATE TABLE "
+ TABLE_NAME
+ " ("
+ COLUMN_UID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COLUMN_VALUE
+ " VARCHAR(100), "
+ COLUMN_DATE_AT
+ " VARCHAR(100));";
private static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;
private Context context; //mContext;
public MyHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
// or mContext = context
this.context = context;
L.t(context, "constructor called");
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(CREATE_TABLE);
L.t(context, "onCreate called");
} catch (SQLException e) {
L.t(context, "" + e);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try {
L.t(context, "onUpgrade called");
db.execSQL(DROP_TABLE);
onCreate(db);
} catch (SQLException e) {
L.t(context, "" + e);
}
}
}
}
Aucun commentaire:
Enregistrer un commentaire