繁体   English   中英

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

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

我有两个片段

AddActivityFragment - 这个 Fragment 负责将数据添加到我的 SQLite 数据库中。

ActivityListFragment - 这个 Fragment 负责在ListView中显示数据

问题在于,每当向 SQLite 表添加数据时,该表在应用程序重新启动之前不会更新。 因此,如果我尝试将一些数据添加到表中,则在重新启动应用程序之前,它不会在ListView中更新。

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

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);
    }
}

您只需使用内容观察器观察 SQLite 数据即可实现所需的行为。 我在这里有一个 Github 项目,它可能会帮助您了解它是如何工作的。

第一步是定义一个唯一的内容 URI。 URI 可能如下所示。

public static final Uri DB_TABLE_USER_URI = Uri
    .parse("sqlite://" + com.package.your.app + "/" + "user_table");

然后使用ActivityListFragment中的LoaderManager.LoaderCallbacks<Cursor>使用CursorLoader回调函数(即onCreateLoaderonLoadFinished等)加载该片段中的用户。 还要在您的onCreateLoader中注册内容观察者。

this.registerContentObserver(cursor, DBConstants.DB_TABLE_USER_URI);

DataBaseHelper class 中添加/更新用户后,您可能还想通知观察者数据库中的数据已更改,以便它在RecyclerView中自动刷新数据。

context.getContentResolver().notifyChange(DBConstants.DB_TABLE_USER_URI, null);

我建议分叉 Github 项目并运行代码以查看它是如何工作的。

暂无
暂无

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

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