简体   繁体   中英

Access New ParseObject (Parse.com) Across Activities (Android)

I'm looking for a way to access a newly created local ParseObject which hasn't yet synced to the Parse cloud server. Since there is no objectId value there's no way to query for the objectId through the local datastore and it appears the localId (which looks like it creates a unique identifier locally) is locked down (otherwise this would be a non-issue as I could use my Content Provider to take care of the details). Since the ParseObject class isn't Serializable of Parcelable I can't pass it through an Intent. To note the complexity of my task I have I have 3 levels of ParseObjects (ParseObject > Array[ParseObjects] > Array[ParseObjects]). Essentially I'm looking to see if Parse has full offline capabilities.

TL:DR Basically I want to be able to access a single ParseObject in a different Activity as soon as it's created. Does this problem have a practical application with Parse and ParseObjects or am I going to have to implement some serious work arounds?

I believe ParseObjects are serializable, so put them into a Bundle and then put that Bundle into an Intent

in the current activity

 Intent mIntent = new Intent(currentActivityReference, DestinationActivity.class);
 Bundle mBundle = new Bundle();
 mBundle.putSerializable("object", mParseObject);
 mIntent.putExtras(mBundle);
 startActivity(mIntent);

in the destination activity

retrieve the intent with getIntent().getExtras() , which is a Bundle object, so there is a getter for the serializable .getSerializable("object") but you will have to cast it to (ParseObject)

So I was able to keep everything within the confines of the structures I already have in place to take care of this problem (a sync adapter and the Parse API). Basically all I had to do was leverage Parse's existing "setObjectId" function.

NOTE: This only works with an existing Content Provider / SQLiteDatabase

I created a temporary unique ID for the new ParseObject to be stored locally. This unique value is based off of the max index number in the Content Provider I'm storing my objects (for my Sync Adapter).

//query to get the max ID from the Content Provider (used with the sync adapter)
Cursor cursor = context.getContentResolver().query(
       WorkoutContract.Entry.CONTENT_URI,
       new String[]{"MAX(" + WorkoutContract.Entry._ID + ")"},
       null, null, null
);
long idx = 1;    //default max index if there are no records
if (cursor.moveToFirst())
   idx = cursor.getInt(0) + 1;
final long maxIndex = idx;
cursor.close();
//this is the temporary ID used for storing, a String constant prepended to the max index
String localID = WorkoutContract.LOCAL_WORKOUT_ID + maxIndex;

I then used the pin() method to store this ParseObject locally and then made an insert into the Content Provider to not only keep the ID in the table to iterate the max index in the table.

//need to insert a dummy value into the Content Provider so the max _ID iterates
ContentValues workoutValues = new ContentValues();
//the COLUMN_WORKOUT_ID constant refers to the column which holds the ParseObjects ID
workoutValues.put(WorkoutContract.Entry.COLUMN_WORKOUT_ID, localID);
context.getContentResolver().insert(
        WorkoutContract.Entry.CONTENT_URI,
        workoutValues);

Then I created another dummy ParseObject with all the same attributes as the one with the local ID (without the local ID). This ParseObject was then saved to the server via the saveEventually() function. (Note: This will create 2 local copies or your ParseObject. To leave the blank copy out of queries simply leave out ParseObjects with null object IDs).

query.whereNotEqualTo("objectId", null);

In the saveEventually() function there needs to be a callback which replaces the old (local) ParseObject as well as the localID value in the Content provider. In the SaveCallback object replace the server returned ParseObject's attributes with the local ones (to account for any changes made during the server query). Below is the full code for the SaveCallback where the tempObject is the one sent to the Parse server:

tempObject.saveEventually(new SaveCallback() {
//changes the local ParseObject's ID to the newly generated one
@Override
public void done(ParseException e) {
    if (e == null) {
        try {
            //replaces the old ParseObject
            tempObject.put(Workout.PARSE_FIELD_NAME, newWorkout.get(Workout.PARSE_FIELD_NAME));
            tempObject.put(Workout.PARSE_FIELD_OWNER, ParseUser.getCurrentUser());
            tempObject.put(Workout.PARSE_FIELD_DESCRIPTION, newWorkout.get(Workout.PARSE_FIELD_DESCRIPTION));
            tempObject.pin();
            newWorkout.unpinInBackground(new DeleteCallback() {
                @Override
                public void done(ParseException e) {
                    Log.i(TAG, "Object unpinned");
                }
            });
        } catch (ParseException e1) {
            e1.printStackTrace();
        }
        //update to content provider with the new ID
        ContentValues mUpdateValues = new ContentValues();
        String mSelectionClause = WorkoutContract.Entry._ID +  "= ?";
        String[] mSelectionArgs = {Long.toString(maxIndex)};
        mUpdateValues.put(WorkoutContract.Entry.COLUMN_WORKOUT_ID, tempObject.getObjectId());
        mUpdateValues.put(WorkoutContract.Entry.COLUMN_UPDATED, tempObject.getUpdatedAt().getTime());
        context.getContentResolver().update(
                WorkoutContract.Entry.CONTENT_URI,
                mUpdateValues,
                mSelectionClause,
                mSelectionArgs
        );
    }
}
});

To get the local ParseObject in another Activity just pass the local objectId in an Intent and load it. However, the index of the ParseObject on the Content Provider needs to be passed as well (or it can be retrieved from the unique local ID) so if the ParseObject is ever retrieved again you can check the Content Provider for the updated Object ID and query the correct ParseObject.

This could use a bit of refinement but for now 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.

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