简体   繁体   中英

How to synchronize on a File object in Android / Java

I have two Fragments and a File that contains a JSON representation of a List<Competitor> . In the first Fragment I create a Competitor . Then I send this Competitor to a background service via an IntentService . In the IntentService if open the File that contains the List<Competitor> , add the Competitor , then re-serialize / re-write the File .

After sending the Competitor to the IntentService , I send the user to the next Fragment (while the background service is writing the file). The problem is that the next screen looks for the same File and attempts to open it, and parse it into a List<Competitor> for use in a RecyclerView . However, if the background service is still writing the File , I will end up with a concurrentModificationException . This hasn't happened because the File write is quick but I want to prevent the possibility.

I was thinking I could synchronize on the File in the two different methods (write and read). I don't know if this is the right way to use synchronize . Below is what I'm thinking:

The write method

 public static void writeMasterCompetitorsFile(Context context, List<Competitor> competitors) {

        File file = new File(context.getFilesDir(), MASTER_COMP_FILE);

        synchronized (file) {
            String jsonString = new Gson().toJson(competitors);

            try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                writer.write(jsonString);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

The read method

public static List getMasterCompetitorsList(Context context) {

List<Competitor> list = new ArrayList<>();
File file = new File(context.getFilesDir(), MASTER_COMP_FILE);

synchronized (file) {
    if (file.exists()) {
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String compList = reader.readLine();
            Type competitorListType = new TypeToken<List<Competitor>>() {
            }.getType();
            list = new Gson().fromJson(compList, competitorListType);
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        writeMasterCompetitorsFile(context, list);
    }
}

Android Studio is telling me that I shouldn't synchronize on a local variable. Do I have the right idea?

Here's an example of using a static object to synchronize.

public static final Object monitor = new Object();

public static void writeMasterCompetitorsFile(Context context, List<Competitor> competitors) {

    File file = new File(context.getFilesDir(), MASTER_COMP_FILE);

    synchronized (monitor) {
        String jsonString = new Gson().toJson(competitors);

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            writer.write(jsonString);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

public static List getMasterCompetitorsList(Context context) {
    List<Competitor> list = new ArrayList<>();
    File file = new File(context.getFilesDir(), MASTER_COMP_FILE);

    synchronized (monitor) {
        if (file.exists()) {
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                String compList = reader.readLine();
                Type competitorListType = new TypeToken<List<Competitor>>() {
                }.getType();
                list = new Gson().fromJson(compList, competitorListType);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            writeMasterCompetitorsFile(context, list);
        }
    }
}

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