diff --git a/src/main/java/rx/functions/ViewAction1.java b/src/main/java/rx/functions/ViewAction1.java new file mode 100644 index 00000000..ddfe3d81 --- /dev/null +++ b/src/main/java/rx/functions/ViewAction1.java @@ -0,0 +1,53 @@ +/** + * Copyright 2014 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.android.functions; + +import android.view.View; + +import rx.functions.Action1; + +import java.lang.ref.WeakReference; + +/** + * An {@link Action1} implementation specific for {@link View}s. + * + * @param the type of {@link View} upon which to perform the action. + * @param the type being observed + */ +public abstract class ViewAction1 implements Action1 { + + private final WeakReference viewReference; + + public ViewAction1(V view) { + viewReference = new WeakReference(view); + } + + @Override + public final void call(T t) { + V view = viewReference.get(); + if (view != null) { + call(view, t); + } + } + + /** + * Implement this instead of {@link Action1#call(Object)}. + * @param view the view given in the constructor. + * @param t the object being observed + */ + public abstract void call(V view, T t); + +} diff --git a/src/main/java/rx/functions/ViewActionSetActivated.java b/src/main/java/rx/functions/ViewActionSetActivated.java index 2eb8c72b..ae19e04a 100644 --- a/src/main/java/rx/functions/ViewActionSetActivated.java +++ b/src/main/java/rx/functions/ViewActionSetActivated.java @@ -17,18 +17,14 @@ import android.view.View; -import rx.functions.Action1; - -public class ViewActionSetActivated implements Action1 { - - private final View view; +public class ViewActionSetActivated extends ViewAction1 { public ViewActionSetActivated(View view) { - this.view = view; + super(view); } @Override - public void call(Boolean aBoolean) { + public void call(View view, Boolean aBoolean) { view.setActivated(aBoolean); } } diff --git a/src/main/java/rx/functions/ViewActionSetClickable.java b/src/main/java/rx/functions/ViewActionSetClickable.java index 3d3e44c7..f1ead351 100644 --- a/src/main/java/rx/functions/ViewActionSetClickable.java +++ b/src/main/java/rx/functions/ViewActionSetClickable.java @@ -17,18 +17,14 @@ import android.view.View; -import rx.functions.Action1; - -public class ViewActionSetClickable implements Action1 { - - private final View view; +public class ViewActionSetClickable extends ViewAction1 { public ViewActionSetClickable(View view) { - this.view = view; + super(view); } @Override - public void call(Boolean aBoolean) { + public void call(View view, Boolean aBoolean) { view.setClickable(aBoolean); } } diff --git a/src/main/java/rx/functions/ViewActionSetEnabled.java b/src/main/java/rx/functions/ViewActionSetEnabled.java index 35ffa5d9..82e6deb1 100644 --- a/src/main/java/rx/functions/ViewActionSetEnabled.java +++ b/src/main/java/rx/functions/ViewActionSetEnabled.java @@ -17,18 +17,14 @@ import android.view.View; -import rx.functions.Action1; - -public class ViewActionSetEnabled implements Action1 { - - private final View view; +public class ViewActionSetEnabled extends ViewAction1 { public ViewActionSetEnabled(View view) { - this.view = view; + super(view); } @Override - public void call(Boolean aBoolean) { + public void call(View view, Boolean aBoolean) { view.setEnabled(aBoolean); } } diff --git a/src/main/java/rx/functions/ViewActionSetFocusable.java b/src/main/java/rx/functions/ViewActionSetFocusable.java index 71b4c938..3bb88238 100644 --- a/src/main/java/rx/functions/ViewActionSetFocusable.java +++ b/src/main/java/rx/functions/ViewActionSetFocusable.java @@ -17,18 +17,14 @@ import android.view.View; -import rx.functions.Action1; - -public class ViewActionSetFocusable implements Action1 { - - private final View view; +public class ViewActionSetFocusable extends ViewAction1 { public ViewActionSetFocusable(View view) { - this.view = view; + super(view); } @Override - public void call(Boolean aBoolean) { + public void call(View view, Boolean aBoolean) { view.setFocusable(aBoolean); } } diff --git a/src/main/java/rx/functions/ViewActionSetSelected.java b/src/main/java/rx/functions/ViewActionSetSelected.java index 48b14d12..866abe57 100644 --- a/src/main/java/rx/functions/ViewActionSetSelected.java +++ b/src/main/java/rx/functions/ViewActionSetSelected.java @@ -17,18 +17,14 @@ import android.view.View; -import rx.functions.Action1; - -public class ViewActionSetSelected implements Action1 { - - private final View view; +public class ViewActionSetSelected extends ViewAction1 { public ViewActionSetSelected(View view) { - this.view = view; + super(view); } @Override - public void call(Boolean aBoolean) { + public void call(View view, Boolean aBoolean) { view.setSelected(aBoolean); } } diff --git a/src/main/java/rx/functions/ViewActionSetVisibility.java b/src/main/java/rx/functions/ViewActionSetVisibility.java index a5a543b6..f281b304 100644 --- a/src/main/java/rx/functions/ViewActionSetVisibility.java +++ b/src/main/java/rx/functions/ViewActionSetVisibility.java @@ -17,11 +17,8 @@ import android.view.View; -import rx.functions.Action1; +public class ViewActionSetVisibility extends ViewAction1 { -public class ViewActionSetVisibility implements Action1 { - - private final View view; private final int visibilityOnFalse; public ViewActionSetVisibility(View view) { @@ -29,18 +26,18 @@ public ViewActionSetVisibility(View view) { } public ViewActionSetVisibility(View view, int visibilityOnFalse) { + super(view); if (visibilityOnFalse != View.GONE && visibilityOnFalse != View.INVISIBLE && visibilityOnFalse != View.VISIBLE) { throw new IllegalArgumentException(visibilityOnFalse + " is not a valid visibility value. See android.view.View VISIBLE, GONE, and INVISIBLE"); } - this.view = view; this.visibilityOnFalse = visibilityOnFalse; } @Override - public void call(Boolean aBoolean) { + public void call(View view, Boolean aBoolean) { int visibility = aBoolean ? View.VISIBLE : visibilityOnFalse; view.setVisibility(visibility); } diff --git a/src/test/java/rx/functions/ViewAction1Test.java b/src/test/java/rx/functions/ViewAction1Test.java new file mode 100644 index 00000000..0222bd2b --- /dev/null +++ b/src/test/java/rx/functions/ViewAction1Test.java @@ -0,0 +1,75 @@ +/** + * Copyright 2014 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.android.functions; + +import android.view.View; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; + +import rx.subjects.PublishSubject; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static rx.android.TestUtil.createView; + +@RunWith(RobolectricTestRunner.class) +public class ViewAction1Test { + + @Test + @SuppressWarnings("unchecked") + public void callIsNotExecutedWithAReleasedReference() { + final View view = null; // simulate a released WeakReference + final PublishSubject subject = PublishSubject.create(); + final ViewAction1Impl action = new ViewAction1Impl(view); + subject.subscribe(action); + + assertFalse(action.wasCalled); + subject.onNext(true); + assertFalse(action.wasCalled); + } + + @Test + @SuppressWarnings("unchecked") + public void callIsExecutedWithARetainedReference() { + final View view = createView(); + final PublishSubject subject = PublishSubject.create(); + final ViewAction1Impl action = new ViewAction1Impl(view); + subject.subscribe(action); + + assertFalse(action.wasCalled); + subject.onNext(true); + assertTrue(action.wasCalled); + } + + private static class ViewAction1Impl extends ViewAction1 { + + boolean wasCalled = false; + + ViewAction1Impl(View view) { + super(view); + } + + @Override + public void call(View view, Boolean aBoolean) { + wasCalled = true; + } + + } + +}