I've got two Fragments
AddActivityFragment
- This Fragment is responsible for adding data into my SQLite database.
and
ActivityListFragment
- This Fragment is responsible for displaying the data in a ListView
The problem is that whenever data is added to the SQLite table, the table is not updated until the application is restarted. Because of this, if I try to add some data into the table, it is not updated in the ListView
until I restart the application.
I've come across adapter.notifyDataSetChanged()
on multiple threads regarding similar problems but I can not for the life of me figure out how I'm supposed to implement this into my own code.
AddActivityFragment.java
:
public class AddActivityFragment extends Fragment implements View.OnClickListener {
private static final String TAG = "AddActivityFragment";
private TextInputLayout activityNameTextField, activityDateTextField;
private TextInputEditText activityNameInput, activityDateInput;
public DatabaseHelper mDatabaseHelper;
private LocationRequest mLocationRequest;
private FusedLocationProviderClient mFusedLocationProviderClient;
private Location mLastLocation;
private ActivityListFragment mActivityListFragment;
private DatePicker mDatePicker;
Context mContext;
private double activityLocationLat;
private double activityLocationLong;
public AddActivityFragment() {
// Required empty public constructor
}
@Override
public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View activityViewFragment = inflater.inflate(R.layout.fragment_add_activity, container, false);
// Get context from fragment.
this.mContext = activityViewFragment.getContext();
mDatabaseHelper = new DatabaseHelper(mContext);
// Find the layout components.
activityNameTextField = activityViewFragment.findViewById(R.id.activityNameTextField);
activityNameInput = activityViewFragment.findViewById(R.id.activityNameInput);
mDatePicker = activityViewFragment.findViewById(R.id.datePicker);
Button addActivityButton = activityViewFragment.findViewById(R.id.addActivityButton);
// Set listener to addActivityButton in this view.
addActivityButton.setOnClickListener(this);
// Set hints for text fields.
activityNameTextField.setHint("Activity Name");
return activityViewFragment;
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.addActivityButton:
StringBuilder sb = new StringBuilder();
int day = mDatePicker.getDayOfMonth();
int month = mDatePicker.getMonth() + 1;
int year = mDatePicker.getYear();
sb.append(day);
sb.append("-");
sb.append(month);
sb.append("-");
sb.append(year);
String activityName = activityNameInput.getText().toString();
String activityDate = sb.toString();
activityNameInput.setText("");
//Add the activity data to the SQL database
mDatabaseHelper.addData(activityName,activityDate,activityLocationLat,activityLocationLong);
break;
default:
break;
}
@Override
public void onResume(){
super.onResume();
Log.d(TAG,"Log when activity is swiped to.");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "List paused.");
}
}
ActivityListFragment.java
:
public class ActivityListFragment extends Fragment {
//Class tag
private static final String TAG = "ActivityListFragment";
private static final String ACTIVITY_LIST_FRAGMENT_TAG = "ACTIVITY_LIST_FRAGMENT";
DatabaseHelper mDatabaseHelper;
Context mContext;
private ListView mListView;
public ArrayAdapter adapter;
private ArrayList<ArrayList> listData;
public ActivityListFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View listViewFragment = inflater.inflate(R.layout.fragment_activity_list, container, false);
this.mContext = listViewFragment.getContext();
mListView = listViewFragment.findViewById(R.id.activity_list_view);
mDatabaseHelper = new DatabaseHelper(mContext);
listData = new ArrayList<>();
for(int i = 0; i < mDatabaseHelper.getRowCount(); i++) {
listData.add(mDatabaseHelper.getDataFromIndex(i));
}
adapter = new ArrayAdapter<>(mContext, android.R.layout.simple_list_item_1, listData);
mListView.setAdapter(adapter);
handleOnItemClick();
return listViewFragment;
}
@Override
public void onResume(){
super.onResume();
Log.d(TAG,"Log when activity is swiped to.");
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "List paused.");
}
ViewPagerAdapter.java
:
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
@NonNull
@Override
public Fragment createFragment(int position) {
switch (position) {
case 0:
return new MapViewFragment();
case 1:
return new AddActivityFragment();
case 2:
return new ActivityListFragment();
}
return null;
}
@Override
public int getItemCount() {
return 3;
}
}
DataBaseHelper.java
:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "DatabaseHelper";
//Table name, column names.
private static final String TABLE_NAME = "activity_table";
private static final String COL_ID = "ID";
private static final String COL_NAME = "name";
private static final String COL_DATE = "date";
private static final String COL_LOCATION_LAT = "location_lat";
private static final String COL_LOCATION = "location_long";
private Cursor mCursor;
ArrayList latLongList;
public DatabaseHelper(Context context) {
super(context, TABLE_NAME, null, 1);
}
/**
* Method: onCreate
* @param db - The database that we are creating the table in.
*/
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_ACTIVITES_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ COL_ID + " INTEGER PRIMARY KEY," + COL_NAME + " VARCHAR,"
+ COL_DATE + " VARCHAR," + COL_LOCATION_LAT + " DOUBLE," + COL_LOCATION + " DOUBLE" + ");";
db.execSQL(CREATE_ACTIVITES_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
/**
* Method: addData
* @param name - The "name"-value which is added to the table column COL_NAME.
* @param date - The "date"-value which is added to the table column COL_DATE.
* @param locationLat - The "locationLat"-value which is added to the table column COL_LOCATION_LAT.
* @param locationLong - The "locationLong"-value which is added to the table column COL_LOCATION_LONG.
* @return true or false, depending if the addition to the table was successful or not.
*/
public boolean addData(String name, String date, Double locationLat, Double locationLong) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_NAME, name);
contentValues.put(COL_DATE, date);
contentValues.put(COL_LOCATION_LAT, locationLat);
contentValues.put(COL_LOCATION, locationLong);
Log.d(TAG, "addData: Adding " + name + " to " + TABLE_NAME);
Log.d(TAG, "addData: Adding " + date + " to " + TABLE_NAME);
Log.d(TAG, "addData: Adding " + locationLat + " to " + TABLE_NAME);
Log.d(TAG, "addData: Adding " + locationLong + " to " + TABLE_NAME);
long result = db.insert(TABLE_NAME, null, contentValues);
if(result == -1) {
Log.d(TAG, "Something went wrong when adding data to database.");
return false;
} else {
Log.d(TAG, "Data correctly added to database");
return true;
}
}
/**
* Method: getData
* @return mCursor - Returns entire table from database.
*/
public Cursor getData() {
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME;
mCursor = db.rawQuery(query, null);
return mCursor;
}
/**
* Method: getDataFromIndex
* @param index - Row index in activity_table table.
* @return list - ArrayList of data at row index.
*/
public ArrayList getDataFromIndex (int index) {
ArrayList list = new ArrayList();
if(mCursor == null) {
getData();
}
mCursor.moveToPosition(index);
list.add(mCursor.getString(1));
list.add(mCursor.getString(2));
list.add(mCursor.getDouble(3));
list.add(mCursor.getDouble(4));
return list;
}
/**
* Method: getRowCount
* @return mCursor.getCount - Total amount of rows in table.
*/
public int getRowCount() {
if(mCursor == null) {
getData();
}
return mCursor.getCount();
}
/** TODO: This might be useless as we will need to fetch the names associated to the activity anyway, to be decided.
* Method: latLongArrayListFromIndex
* @param index - Row index in activity_table table.
* @return latLongList - ArrayList of data at row index.
*/
public ArrayList latLongArrayListFromIndex(int index) {
latLongList = new ArrayList();
if(mCursor == null) {
getData();
}
mCursor.moveToPosition(index);
latLongList.add(mCursor.getDouble(mCursor.getColumnIndex("location_lat")));
latLongList.add(mCursor.getDouble(mCursor.getColumnIndex("location_long")));
return latLongList;
}
/**
* Method getItemId
*/
public Cursor getItemId(String name) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT " + COL_ID + " FROM " + TABLE_NAME + " WHERE " + COL_NAME + " = '" + name + "'";
Cursor data = db.rawQuery(query, null);
return data;
}
/**
* Method: updateName
* @param newName
* @param id
* @param oldName
*/
public void updateName(String newName, int id, String oldName) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "UPDATE " + TABLE_NAME + " SET " + COL_NAME + " = '" + newName + "' WHERE " + COL_ID + " = '" + id + "'" + " AND " + COL_NAME + " = '" + oldName + "'";
Log.d(TAG, "updateName: query: " + query);
Log.d(TAG, "updateName: Setting new name of activity to: " + newName);
db.execSQL(query);
}
public void deleteActivity(int id, String name) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "DELETE FROM " + TABLE_NAME + " WHERE " + COL_ID + " = '" + id + "'" + " AND " + COL_NAME + " = '" + name + "'";
Log.d(TAG, "deleteActivity: query: " + query);
Log.d(TAG, "deleteActivity: Deleting " + name + " from table");
db.execSQL(query);
}
}
You can achieve the desired behaviour just by observing the SQLite data using content observer. I have a Github project here , that might help you to understand how this works.
The first step would be defining a content URI that is unique. The URI might look something as follows.
public static final Uri DB_TABLE_USER_URI = Uri
.parse("sqlite://" + com.package.your.app + "/" + "user_table");
Then use the LoaderManager.LoaderCallbacks<Cursor>
in your ActivityListFragment
to load the users in that fragment using CursorLoader
callback functions (ie onCreateLoader
, onLoadFinished
, etc.). Also register for content observer in your onCreateLoader
.
this.registerContentObserver(cursor, DBConstants.DB_TABLE_USER_URI);
And after you add/update a user in your DataBaseHelper
class, you might also want to notify the observer that the data is changed in your database, so that it refreshes the data automatically in the RecyclerView
.
context.getContentResolver().notifyChange(DBConstants.DB_TABLE_USER_URI, null);
I would recommend forking the Github project and run the code to see how it works.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.