跨活动(Android)访问新的ParseObject(Parse.com)

跨活动(Android)访问新的ParseObject(Parse.com),android,android-activity,parse-platform,Android,Android Activity,Parse Platform,我正在寻找一种方法来访问一个新创建的本地ParseObject,它还没有同步到ParseCloud服务器。由于没有objectId值,因此无法通过本地数据存储查询objectId,并且似乎本地ID(看起来它在本地创建了唯一标识符)被锁定,否则这将不是问题,因为我可以使用我的内容提供商来处理细节。由于ParseObject类不能序列化Parcelable,因此我无法将其传递给Intent。要注意我的任务的复杂性,我有3个级别的ParseObjects ParseObject>Array[Parse

我正在寻找一种方法来访问一个新创建的本地ParseObject,它还没有同步到ParseCloud服务器。由于没有objectId值,因此无法通过本地数据存储查询objectId,并且似乎本地ID(看起来它在本地创建了唯一标识符)被锁定,否则这将不是问题,因为我可以使用我的内容提供商来处理细节。由于ParseObject类不能序列化Parcelable,因此我无法将其传递给Intent。要注意我的任务的复杂性,我有3个级别的ParseObjects ParseObject>Array[ParseObjects]>Array[ParseObjects]。本质上,我想看看Parse是否具有完整的脱机功能

TL:DR
基本上,我希望在创建一个ParseObject后,能够在另一个活动中访问它。这个问题是否在Parse和ParseObjects中有实际应用,或者我必须实施一些严肃的解决方法?

我认为ParseObjects是可序列化的,所以将它们放入一个Bundle中,然后将该Bundle放入一个Intent中

在当前活动中

 Intent mIntent = new Intent(currentActivityReference, DestinationActivity.class);
 Bundle mBundle = new Bundle();
 mBundle.putSerializable("object", mParseObject);
 mIntent.putExtras(mBundle);
 startActivity(mIntent);
在目的地活动中


使用getIntent.getExtras检索意图,这是一个Bundle对象,因此serializable.getSerializableobject有一个getter,但您必须将其强制转换为ParseObject,因此我能够将所有内容都限制在我已经存在的结构范围内,以解决此问题—同步适配器和解析API。基本上,我所要做的就是利用Parse现有的setObjectId函数

注意:这仅适用于现有的内容提供商/SQLiteDatabase

我为本地存储的新ParseObject创建了一个临时唯一ID。此唯一值基于我为同步适配器存储对象的内容提供程序中的最大索引号

//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;
然后,我使用pin方法在本地存储这个ParseObject,然后向内容提供程序中插入一个元素,这样不仅可以在表中保留ID,还可以迭代表中的max索引

//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);
然后,我创建了另一个虚拟ParseObject,它的属性与具有本地ID但没有本地ID的ParseObject的属性相同。然后,通过saveFinally函数将该ParseObject保存到服务器。注意:这将创建2个本地副本或ParseObject。若要将空白副本排除在查询之外,只需删除具有空对象ID的PARSEObject。

query.whereNotEqualTo("objectId", null);
在savefinally函数中,需要有一个回调函数来替换旧的本地ParseObject以及内容提供程序中的localID值。在SaveCallback对象中,将服务器返回的ParseObject属性替换为本地属性,以说明在服务器查询期间所做的任何更改。下面是SaveCallback的完整代码,其中tempObject是发送到解析服务器的对象:

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
        );
    }
}
});
要在另一个活动中获取本地ParseObject,只需在Intent中传递本地objectId并加载它。但是,还需要传递内容提供程序上ParseObject的索引,或者可以从唯一的本地ID检索该索引,因此,如果再次检索ParseObject,您可以检查内容提供程序以获取更新的对象ID,并查询正确的ParseObject


这可能需要一些改进,但目前它可以工作。

感谢您的输入。但是,putSerializable函数无法将ParseObject识别为可序列化对象,因为无法将错误应用于给定的类型。在它的文档中也没有提到ParseObject实现Serializable/Parcelable接口@c0d3blooded好的,在这种情况下,我认为您必须在本地保存parse对象,并通过ID在本地重新查询它。这是我最初要做的,但是ParseObjects只在服务器回调后创建它们的ID,因此没有数据连接就没有ID。创建时有一个具有唯一标识符的本地ID属性,但Parse通过变量、函数或查询搜索使其无法访问,因此我无法通过该ID编制索引。再次查看文档后,我发现setObjectId函数可能很有用,即使Parse说不要使用它…@c0d3blooded,那么您应该通过一个意图包传递您的适用数据,稍后创建您的ParseObject。我会看看我能做些什么。即使我可以通过意图传递数据,当再次访问ParseObject时,它也需要在某个点建立索引以进行保存和更新。因此,即使我能够创建ParseObject,我也无法再次引用它,直到我从服务器收到一个回调,该回调删除了脱机选项。尝试使用ParseObject.toString获取可读表单。如果是,则可以通过intent accross活动将该对象作为字符串发送。我会在有机会时查看它,但因为toString方法没有出现在中,我只能猜测它使用的toString方法是Java的默认Object.toS 翻译成乱码的字符串方法。看起来也没有函数可以根据toString方法的结果重构ParseObject。