简体   繁体   English

当 SQLite 数据库在另一个 Fragment 中更新时更新 Fragment 中的 ListView

[英]Update ListView in Fragment when SQLite database is updated in another Fragment

I've got two Fragments我有两个片段

AddActivityFragment - This Fragment is responsible for adding data into my SQLite database. AddActivityFragment - 这个 Fragment 负责将数据添加到我的 SQLite 数据库中。

and

ActivityListFragment - This Fragment is responsible for displaying the data in a ListView ActivityListFragment - 这个 Fragment 负责在ListView中显示数据

The problem is that whenever data is added to the SQLite table, the table is not updated until the application is restarted.问题在于,每当向 SQLite 表添加数据时,该表在应用程序重新启动之前不会更新。 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.因此,如果我尝试将一些数据添加到表中,则在重新启动应用程序之前,它不会在ListView中更新。

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.我在多个线程上遇到过关于类似问题的adapter.notifyDataSetChanged() ,但我一生都无法弄清楚我应该如何将其实现到我自己的代码中。

AddActivityFragment.java : 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 : 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 : 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 : 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.您只需使用内容观察器观察 SQLite 数据即可实现所需的行为。 I have a Github project here , that might help you to understand how this works.我在这里有一个 Github 项目,它可能会帮助您了解它是如何工作的。

The first step would be defining a content URI that is unique.第一步是定义一个唯一的内容 URI。 The URI might look something as follows. URI 可能如下所示。

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.).然后使用ActivityListFragment中的LoaderManager.LoaderCallbacks<Cursor>使用CursorLoader回调函数(即onCreateLoaderonLoadFinished等)加载该片段中的用户。 Also register for content observer in your onCreateLoader .还要在您的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 .DataBaseHelper class 中添加/更新用户后,您可能还想通知观察者数据库中的数据已更改,以便它在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.我建议分叉 Github 项目并运行代码以查看它是如何工作的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM