简体   繁体   English

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

[英]Android: Parse.com concurrency issue with findInBackground()

I am using Parse.com as a backend for my app. 我正在使用Parse.com作为我的应用程序的后端。 The local database from Parse seems to be very easy to use, so I decided to use it. Parse的本地数据库似乎非常易于使用,因此我决定使用它。

I want to create a database with Name and PhoneNumber . 我想用NamePhoneNumber创建一个数据库。 That is easy, just make a new ParseObject and pinInBackground() . 这很容易,只需创建一个new ParseObject pinInBackground()pinInBackground() But it is more complicated when I want to remove duplicate numbers. 但是,当我要删除重复的数字时,情况会更加复杂。 First I need to search if the number already exists in the database and then add the new number if it doesn't exists. 首先,我需要搜索数据库中是否已经存在该号码,然后如果不存在则添加新号码。

The method to do this is: 这样做的方法是:

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

}

Lets say I want to add 3 persons in the database: 假设我要在数据库中添加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

Notice that first and third person have the same number so the third souldn't be added to database, but... 请注意,第一人称和第三人称具有相同的数字,因此不会将第三个灵魂添加到数据库中,但是...

The logcat after this is: 之后的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

The last line from logcat is from the method that shows me all persons from database: 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());
            }

        }
    });
}

So there are 2 problems: 所以有两个问题:

  1. The third number is added even if I checked if already exists. 即使我检查是否已经存在,也会添加第三个数字。

  2. The method that shows me all persons tell me I have nothing in my database even if in logcat I can see it added 3 persons. 向所有人显示的方法告诉我,即使在logcat中我看不到它添加了3个人,我的数据库中也没有任何内容。

I think the problem is findInBackground() method that does all the job in another thread. 我认为问题是在另一个线程中完成所有工作的findInBackground()方法。 Is there any solution to this problem? 有什么解决办法吗?

Both of your problems are a result of asynchronous work. 您的两个问题都是异步工作的结果。 If you call the putPerson method twice, they will both run near-simultaneously in separate background threads and both find-queries will most likely return almost at the same time, and definitely before the first call has saved the new person. 如果您两次调用putPerson方法,它们将同时在单独的后台线程中运行,并且两个查找查询几乎都将同时返回,并且肯定是在第一次调用保存新人员之前。

In your example, the getPerson call will return before the background threads have been able to save your three people as well. 在您的示例中, getPerson调用将在后台线程也能够保存您的三个人之前返回。

Your problem is not really related to Parse or localDataStore, but is a typical concurrency issue. 您的问题实际上与Parse或localDataStore无关,而是典型的并发问题。 You need to rethink how you handle concurrency in your app. 您需要重新考虑如何处理应用程序中的并发。

As long as this is only a local issue, you can impose synchronous structure with ie the Bolts Framework (which is already a part of your app since you're using Parse). 只要这只是一个本地问题,您就可以使用Bolts框架 (由于使用Parse而已成为应用程序的一部分)强加了同步结构。 But if calls to addPerson is done in multiple places, you will always face this problem and you'd have to find other solutions or workarounds to handle concurrency. 但是,如果在多个地方都对addPerson进行了调用,那么您将始终会遇到此问题,并且必须找到其他解决方案或变通办法来处理并发。

Concurrency is a big topic which you should spend some time studying. 并发是一个大话题,您应该花一些时间研究。

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

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