Android:与findInBackground()的Parse.com并发问题

时间:2015-12-26 13:56:47

标签: java android parse-platform

我正在使用Parse.com作为我应用的后端。来自Parse的本地数据库似乎非常容易使用,因此我决定使用它。

我想创建一个包含NamePhoneNumber的数据库。这很简单,只需制作new ParseObjectpinInBackground()即可。但是当我想删除重复的数字时,它会更复杂。首先,我需要搜索数据中是否已存在该数字,然后添加新数字(如果该数字不存在)。

执行此操作的方法是:

 public void putPerson(final String name, final String phoneNumber, final boolean isFav) {

    // Verify if there is any person with the same phone number
    ParseQuery<ParseObject> query = ParseQuery.getQuery(ParseClass.PERSON_CLASS);
    query.whereEqualTo(ParseKey.PERSON_PHONE_NUMBER_KEY, phoneNumber);
    query.fromLocalDatastore();
    query.findInBackground(new FindCallback<ParseObject>() {
                               public void done(List<ParseObject> personList,
                                                ParseException e) {
                                   if (e == null) {
                                       if (personList.isEmpty()) {
                                           // If there is not any person with the same phone number add person
                                           ParseObject person = new ParseObject(ParseClass.PERSON_CLASS);
                                           person.put(ParseKey.PERSON_NAME_KEY, name);
                                           person.put(ParseKey.PERSON_PHONE_NUMBER_KEY, phoneNumber);
                                           person.put(ParseKey.PERSON_FAVORITE_KEY, isFav);

                                           person.pinInBackground();
                                       } else {
                                           Log.d(TAG, "Warning: " + "Person with the number " + phoneNumber + " already exists.");
                                       }
                                   } else {
                                       Log.d(TAG, "Error: " + e.getMessage());
                                   }
                               }
                           }
    );

}

假设我想在数据库中添加3个人:

    ParseLocalDataStore.getInstance().putPerson("Jack", "0741234567", false);
    ParseLocalDataStore.getInstance().putPerson("John", "0747654321", false);
    ParseLocalDataStore.getInstance().putPerson("Jack", "0741234567", false);
    ParseLocalDataStore.getInstance().getPerson(); // Get all persons from database

请注意,第一个和第三个人具有相同的编号,因此第三个人不能添加到数据库中,但是......

此后的logcat是:

12-26 15:37:55.424 16408-16408/D/MGParseLocalDataStore: Person:0741234567 was added.
12-26 15:37:55.424 16408-16408/D/MGParseLocalDataStore: Person:0747654321 was added.
12-26 15:37:55.484 16408-16408/D/MGParseLocalDataStore: Person:0741234567 was added.
12-26 15:37:55.494 16408-16408/D/MGParseLocalDataStore: Person database is empty

logcat的最后一行来自向我展示数据库中所有人的方法:

public void getPerson() {
        ParseQuery<ParseObject> query = ParseQuery.getQuery(ParseClass.PERSON_CLASS);
        query.fromLocalDatastore();
        query.findInBackground(new FindCallback<ParseObject>() {
            public void done(List<ParseObject> personList,
                             ParseException e) {
                if (e == null) {
                    if (personList.isEmpty()) {
                        Log.d(TAG, "Person database is empty");
                    } else {
                    for (ParseObject p : personList) {
                        Log.d(TAG, p.getString(ParseKey.PERSON_PHONE_NUMBER_KEY));
                    }
                }
            } else {
                Log.d(TAG, "Error: " + e.getMessage());
            }

        }
    });
}

所以有两个问题:

  1. 即使我检查了是否已存在,也会添加第三个数字。

  2. 向我显示所有人的方法告诉我,我的数据库中没有任何内容,即使在logcat中我可以看到它增加了3个人。

  3. 我认为问题是findInBackground()方法,它在另一个线程中完成所有工作。 有没有解决这个问题的方法?

1 个答案:

答案 0 :(得分:1)

您的两个问题都是异步工作的结果。如果你两次调用putPerson方法,它们将在不同的后台线程中同时运行,并且两个查找查询几乎可能几乎同时返回,并且肯定在第一次调用保存新人之前。

在您的示例中,getPerson调用将在后台线程能够保存您的三个人之前返回。

您的问题与Parse或localDataStore无关,但这是一个典型的并发问题。您需要重新考虑如何在应用程序中处理并发性。

只要这只是一个本地问题,你就可以强加同步结构,即Bolts Framework(因为你正在使用Parse,它已经是你应用程序的一部分)。但是如果对addPerson的调用是在多个地方完成的,那么您将始终面临这个问题,并且您必须找到其他解决方案或解决方法来处理并发问题。

并发是一个很重要的话题,你应该花些时间学习。