WorkerHandler survives config changes (#29)

* Weak cache for threads

* Add logs

* Fix manifest
pull/30/head^2
Mattia Iavarone 7 years ago committed by GitHub
parent 53bb5baf42
commit cce8d6e621
  1. 24
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/WorkerHandlerTest.java
  2. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  3. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  4. 32
      cameraview/src/main/utils/com/otaliastudios/cameraview/WorkerHandler.java
  5. 10
      demo/src/main/AndroidManifest.xml

@ -0,0 +1,24 @@
package com.otaliastudios.cameraview;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class WorkerHandlerTest {
@Test
public void testCache() {
WorkerHandler w1 = WorkerHandler.get("handler1");
WorkerHandler w1a = WorkerHandler.get("handler1");
WorkerHandler w2 = WorkerHandler.get("handler2");
assertTrue(w1 == w1a);
assertFalse(w1 == w2);
}
}

@ -35,7 +35,7 @@ abstract class CameraController implements Preview.SurfaceCallback {
mCameraCallbacks = callback; mCameraCallbacks = callback;
mPreview = preview; mPreview = preview;
mPreview.setSurfaceCallback(this); mPreview.setSurfaceCallback(this);
mHandler = new WorkerHandler("CameraViewController"); mHandler = WorkerHandler.get("CameraViewController");
} }
//region Start&Stop //region Start&Stop

@ -117,7 +117,7 @@ public class CameraView extends FrameLayout {
mPreviewImpl = instantiatePreview(context, this); mPreviewImpl = instantiatePreview(context, this);
mCameraController = instantiateCameraController(mCameraCallbacks, mPreviewImpl); mCameraController = instantiateCameraController(mCameraCallbacks, mPreviewImpl);
mUiHandler = new Handler(Looper.getMainLooper()); mUiHandler = new Handler(Looper.getMainLooper());
mWorkerHandler = new WorkerHandler("CameraViewWorker"); mWorkerHandler = WorkerHandler.get("CameraViewWorker");
// Views // Views
mGridLinesLayout = new GridLinesLayout(context); mGridLinesLayout = new GridLinesLayout(context);

@ -3,17 +3,43 @@ package com.otaliastudios.cameraview;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Class holding a background handler. * Class holding a background handler.
* Using setDaemon right now but a better approach would be to have * We want them to survive configuration changes if there's still job to do.
* start() and stop() callbacks here. TODO
*/ */
class WorkerHandler { class WorkerHandler {
private final static CameraLogger LOG = CameraLogger.create(WorkerHandler.class.getSimpleName());
private final static ConcurrentHashMap<String, WeakReference<WorkerHandler>> sCache = new ConcurrentHashMap<>(4);
public static WorkerHandler get(String name) {
if (sCache.containsKey(name)) {
WorkerHandler cached = sCache.get(name).get();
if (cached != null) {
HandlerThread thread = cached.mThread;
if (thread.isAlive() && !thread.isInterrupted()) {
LOG.w("get:", "Reusing cached worker handler.", name);
return cached;
}
}
LOG.w("get:", "Thread reference died, removing.", name);
sCache.remove(name);
}
LOG.i("get:", "Creating new handler.", name);
WorkerHandler handler = new WorkerHandler(name);
sCache.put(name, new WeakReference<>(handler));
return handler;
}
private HandlerThread mThread; private HandlerThread mThread;
private Handler mHandler; private Handler mHandler;
public WorkerHandler(String name) { private WorkerHandler(String name) {
mThread = new HandlerThread(name); mThread = new HandlerThread(name);
mThread.setDaemon(true); mThread.setDaemon(true);
mThread.start(); mThread.start();

@ -13,18 +13,18 @@
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name="com.otaliastudios.cameraview.demo.MainActivity" android:name=".MainActivity"
android:theme="@style/Theme.MainActivity"> android:theme="@style/Theme.MainActivity"
android:configChanges="orientation|screenLayout|keyboardHidden">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity android:name=".PicturePreviewActivity" />
android:name="com.otaliastudios.cameraview.demo.PicturePreviewActivity" />
<activity android:name="com.otaliastudios.cameraview.demo.VideoPreviewActivity"/> <activity android:name=".VideoPreviewActivity"/>
</application> </application>

Loading…
Cancel
Save