[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