[Android] ThumbnailerManager: remove the singleton to avoid a context leak

Ludovic Fauvet git at videolan.org
Sat Sep 29 16:18:27 CEST 2012


vlc-ports/android | branch: master | Ludovic Fauvet <etix at videolan.org> | Sat Sep 29 14:39:04 2012 +0200| [879830d50b4b3bcdc5bbdc3c343dde45c1e831d6] | committer: Ludovic Fauvet

ThumbnailerManager: remove the singleton to avoid a context leak

Reported-by: Sébastien Toque <xilasz at gmail.com>

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

 .../src/org/videolan/vlc/ThumbnailerManager.java   |   36 +++++++++-----------
 .../src/org/videolan/vlc/gui/MainActivity.java     |   11 ++++--
 .../videolan/vlc/gui/video/VideoListFragment.java  |   14 ++++++--
 3 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/vlc-android/src/org/videolan/vlc/ThumbnailerManager.java b/vlc-android/src/org/videolan/vlc/ThumbnailerManager.java
index 71d385b..5709003 100644
--- a/vlc-android/src/org/videolan/vlc/ThumbnailerManager.java
+++ b/vlc-android/src/org/videolan/vlc/ThumbnailerManager.java
@@ -32,16 +32,16 @@ import java.util.concurrent.locks.ReentrantLock;
 import org.videolan.vlc.gui.MainActivity;
 import org.videolan.vlc.gui.video.VideoListFragment;
 
-import android.app.Activity;
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.Display;
 
 public class ThumbnailerManager implements Runnable {
     public final static String TAG = "VLC/ThumbnailerManager";
 
-    private static ThumbnailerManager mInstance;
     private VideoListFragment mVideoListFragment;
 
     private final Queue<Media> mItems = new LinkedList<Media>();
@@ -52,32 +52,27 @@ public class ThumbnailerManager implements Runnable {
 
     protected Thread mThread;
     private LibVLC mLibVlc;
-    private final Activity mActivity;
+    private final Context mContext;
     private int totalCount;
     private final float mDensity;
 
-    private ThumbnailerManager(Activity parentActivity) {
-        mActivity = parentActivity;
+    public ThumbnailerManager(Context context, Display display) {
         try {
             mLibVlc = LibVLC.getInstance();
         } catch (LibVlcException e) {
             e.printStackTrace();
         }
 
+        mContext = context;
         DisplayMetrics metrics = new DisplayMetrics();
-        mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+        display.getMetrics(metrics);
         mDensity = metrics.density;
     }
 
-    public static ThumbnailerManager getInstance(Activity activity) {
-        if (mInstance == null)
-            mInstance = new ThumbnailerManager(activity);
-        return mInstance;
-    }
-
     public void start(VideoListFragment videoListFragment) {
         if (mThread == null || mThread.getState() == State.TERMINATED) {
             mVideoListFragment = videoListFragment;
+            mVideoListFragment.setThumbnailerManager(this);
             isStopping = false;
             mThread = new Thread(this);
             mThread.start();
@@ -121,7 +116,7 @@ public class ThumbnailerManager implements Runnable {
 
         Log.d(TAG, "Thumbnailer started");
 
-        String prefix = mActivity.getResources().getString(R.string.thumbnail);
+        String prefix = mContext.getResources().getString(R.string.thumbnail);
 
         while (!isStopping) {
             lock.lock();
@@ -129,8 +124,8 @@ public class ThumbnailerManager implements Runnable {
             boolean killed = false;
             while (mItems.size() == 0) {
                 try {
-                    MainActivity.hideProgressBar(mActivity);
-                    MainActivity.clearTextInfo(mActivity);
+                    MainActivity.hideProgressBar(mContext);
+                    MainActivity.clearTextInfo(mContext);
                     totalCount = 0;
                     notEmpty.await();
                 } catch (InterruptedException e) {
@@ -146,9 +141,9 @@ public class ThumbnailerManager implements Runnable {
             Media item = mItems.poll();
             lock.unlock();
 
-            MainActivity.showProgressBar(mActivity);
+            MainActivity.showProgressBar(mContext);
 
-            MainActivity.sendTextInfo(mActivity, String.format("%s %s", prefix, item.getFileName()), count, total);
+            MainActivity.sendTextInfo(mContext, String.format("%s %s", prefix, item.getFileName()), count, total);
             count++;
 
             int width = (int) (120 * mDensity);
@@ -160,7 +155,7 @@ public class ThumbnailerManager implements Runnable {
             byte[] b = mLibVlc.getThumbnail(item.getLocation(), width, height);
 
             if (b == null) {// We were not able to create a thumbnail for this item.
-                item.setPicture(mActivity, null);
+                item.setPicture(mContext, null);
                 continue;
             }
 
@@ -169,7 +164,7 @@ public class ThumbnailerManager implements Runnable {
 
             Log.i(TAG, "Thumbnail created for " + item.getFileName());
 
-            item.setPicture(mActivity, thumbnail);
+            item.setPicture(mContext, thumbnail);
             // Post to the file browser the new item.
             mVideoListFragment.setItemToUpdate(item);
 
@@ -182,6 +177,9 @@ public class ThumbnailerManager implements Runnable {
                 break;
             }
         }
+        /* cleanup */
+        mVideoListFragment.setThumbnailerManager(null);
+        mVideoListFragment = null;
         Log.d(TAG, "Thumbnailer stopped");
     }
 }
diff --git a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
index 18e3ddb..c21e02d 100644
--- a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
@@ -93,6 +93,7 @@ public class MainActivity extends SherlockFragmentActivity {
     private SidebarAdapter mSidebarAdapter;
     private AudioMiniPlayer mAudioPlayer;
     private AudioServiceController mAudioController;
+    private ThumbnailerManager mThumbnailerManager;
     private View mInfoLayout;
     private ProgressBar mInfoProgress;
     private TextView mInfoText;
@@ -262,6 +263,10 @@ public class MainActivity extends SherlockFragmentActivity {
 
         /* Load media items from database and storage */
         MediaLibrary.getInstance(this).loadMediaItems(this);
+
+        /* Load the thumbnailer */
+        mThumbnailerManager = new ThumbnailerManager(this,
+                getWindowManager().getDefaultDisplay());
     }
 
     private void updateMenuOffset() {
@@ -307,7 +312,7 @@ public class MainActivity extends SherlockFragmentActivity {
 
         /* Start the thumbnailer */
         VideoListFragment f = (VideoListFragment)mSidebarAdapter.getFragment("video");
-        ThumbnailerManager.getInstance(this).start(f);
+        mThumbnailerManager.start(f);
 
         super.onResume();
     }
@@ -320,7 +325,7 @@ public class MainActivity extends SherlockFragmentActivity {
         /* Stop scanning for files */
         MediaLibrary.getInstance(this).stop();
         /* Stop the thumbnailer */
-        ThumbnailerManager.getInstance(this).stop();
+        mThumbnailerManager.stop();
 
         SharedPreferences.Editor editor = getSharedPreferences("MainActivity", MODE_PRIVATE).edit();
         editor.putString("fragment", mCurrentFragment);
@@ -334,7 +339,7 @@ public class MainActivity extends SherlockFragmentActivity {
         try {
             unregisterReceiver(messageReceiver);
         } catch (IllegalArgumentException e) {}
-        ThumbnailerManager.getInstance(this).clearJobs();
+        mThumbnailerManager.clearJobs();
         super.onDestroy();
     }
 
diff --git a/vlc-android/src/org/videolan/vlc/gui/video/VideoListFragment.java b/vlc-android/src/org/videolan/vlc/gui/video/VideoListFragment.java
index 53c3129..17afa7c 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoListFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoListFragment.java
@@ -79,6 +79,7 @@ public class VideoListFragment extends SherlockListFragment implements ISortable
     protected static final int UPDATE_ITEM = 0;
 
     private MediaLibrary mMediaLibrary;
+    private ThumbnailerManager mThumbnailerManager;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -245,10 +246,13 @@ public class VideoListFragment extends SherlockListFragment implements ISortable
 
     private void updateList() {
 
+        if (mThumbnailerManager == null) {
+            Log.w(TAG, "Can't update the list, thumbnailer missing");
+            return;
+        }
         List<Media> itemList = mMediaLibrary.getVideoItems();
 
-        ThumbnailerManager t = ThumbnailerManager.getInstance(getActivity());
-        t.clearJobs();
+        mThumbnailerManager.clearJobs();
         mVideoAdapter.clear();
 
         if (itemList.size() > 0) {
@@ -256,7 +260,7 @@ public class VideoListFragment extends SherlockListFragment implements ISortable
                 if (item.getType() == Media.TYPE_VIDEO) {
                     mVideoAdapter.add(item);
                     if (item.getPicture() == null && !item.isPictureParsed())
-                        t.addJob(item);
+                        mThumbnailerManager.addJob(item);
                 }
             }
             mVideoAdapter.sort();
@@ -307,4 +311,8 @@ public class VideoListFragment extends SherlockListFragment implements ISortable
         intent.setAction(ACTION_SCAN_STOP);
         context.getApplicationContext().sendBroadcast(intent);
     }
+
+    public void setThumbnailerManager(ThumbnailerManager thumbnailerManager) {
+        mThumbnailerManager = thumbnailerManager;
+    }
 }



More information about the Android mailing list