[Android] Fix a very annoying IllegalStateException involving duplicate fragments

Edward Wang git at videolan.org
Sun Mar 3 23:15:51 CET 2013


vlc-ports/android | branch: master | Edward Wang <edward.c.wang at compdigitec.com> | Sat Mar  2 15:02:35 2013 -0500| [c2bcced631856b61d6c3075726c9f7aa0f14cd3e] | committer: Edward Wang

Fix a very annoying IllegalStateException involving duplicate fragments

> http://git.videolan.org/gitweb.cgi/vlc-ports/android.git/?a=commit;h=c2bcced631856b61d6c3075726c9f7aa0f14cd3e
---

 .../src/org/videolan/vlc/gui/MainActivity.java     |    8 +++-
 .../src/org/videolan/vlc/gui/SidebarAdapter.java   |   42 ++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
index 29088ad..d018fb0 100644
--- a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
@@ -382,11 +382,17 @@ public class MainActivity extends SherlockFragmentActivity {
     {
         Fragment fragment = mSidebarAdapter.fetchFragment(id);
 
-        if (!fragment.isAdded())
+        // Prevent fragment from being added twice. (IllegalStateException)
+        // See http://stackoverflow.com/questions/13745787/fragment-already-added-support-lib
+        mSidebarAdapter.lockSemaphore();
+        if(!mSidebarAdapter.isFragmentAdded(id)) {
             getSupportFragmentManager()
                 .beginTransaction()
                 .add(R.id.fragment_placeholder, fragment, id)
                 .commitAllowingStateLoss();
+            mSidebarAdapter.setFragmentAdded(id);
+        }
+        mSidebarAdapter.unlockSemaphore();
 
         /* Start the thumbnailer */
         if (id.equals("video"))
diff --git a/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java b/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java
index cf901aa..b616f3f 100644
--- a/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java
@@ -23,6 +23,7 @@ package org.videolan.vlc.gui;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.Semaphore;
 
 import org.videolan.vlc.R;
 import org.videolan.vlc.Util;
@@ -62,6 +63,8 @@ public class SidebarAdapter extends BaseAdapter {
     private LayoutInflater mInflater;
     static final List<SidebarEntry> entries;
     private HashMap<String, Fragment> mFragments;
+    private HashMap<String, Boolean> mFragmentAdded;
+    private Semaphore mSemaphore;
 
     static {
         SidebarEntry entries2[] = {
@@ -78,6 +81,8 @@ public class SidebarAdapter extends BaseAdapter {
     public SidebarAdapter() {
         mInflater = LayoutInflater.from(VLCApplication.getAppContext());
         mFragments = new HashMap<String, Fragment>(entries.size());
+        mFragmentAdded = new HashMap<String, Boolean>(entries.size());
+        mSemaphore = new Semaphore(1, true);
     }
 
     @Override
@@ -132,6 +137,43 @@ public class SidebarAdapter extends BaseAdapter {
         }
         f.setRetainInstance(true);
         mFragments.put(id, f);
+        mFragmentAdded.put(id, false);
         return f;
     }
+
+    /**
+     * Has the fragment already been added?
+     * Note: lock must be held prior to entering this function!
+     *
+     * @return true if already added
+     */
+    public boolean isFragmentAdded(String id) {
+        return mFragmentAdded.get(id);
+    }
+
+    /**
+     * Flags the fragment as added.
+     *
+     * @param id ID of the fragment
+     */
+    public void setFragmentAdded(String id) {
+        mFragmentAdded.put(id, true);
+    }
+
+    /**
+     * Locks the semaphore before manipulating the added flag, since only one
+     * add operation is permitted.
+     *
+     * Remember to unlockSemaphore() when done.
+     */
+    public void lockSemaphore() {
+        mSemaphore.acquireUninterruptibly();
+    }
+
+    /**
+     * Release the semaphore when done.
+     */
+    public void unlockSemaphore() {
+        mSemaphore.release();
+    }
 }



More information about the Android mailing list