Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
* When used standalone in an {@link EFragment} or in conjunction with the
* {@link UiThread} or {@link Background} annotations, the annotated method will
* be wrapped in an 'if attached' block such that no code will be executed if
* the {@link EFragment} is no longer bound to its parent activity.
* the {@link EFragment} is no longer bound to its parent activity or
* <code>DETACHED</code>the {@link EFragment} views are destroyed
* <code>VIEW_DESTROYED</code>.
* </p>
* <p>
* Should be used on method that must meet the following criteria
Expand All @@ -47,13 +49,13 @@
* ...
*
* &#064;UiThread
* &#064;IgnoredWhenDetached
* &#064;IgnoreWhen(IgnoreWhen.State.DETACHED)
* void killActivity() {
* getActivity().finish();
* }
*
*
* &#064;IgnoredWhenDetached
* &#064;IgnoreWhen(IgnoreWhen.State.VIEW_DESTROYED)
* void updateTitle(String title) {
* getActivity().setTitle(title);
* }
Expand All @@ -69,6 +71,29 @@
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface IgnoredWhenDetached {
public @interface IgnoreWhen {

/**
* The lifecycle state after the method should not be executed.
*
* @return the state that skips method execution
*/
State value();

/**
* The lifecycle state after the method should not be executed.
*/
enum State {

/**
* Skip execution if the {@link EFragment} is no longer bound to its
* parent activity.
*/
DETACHED,

/**
* Skip execution if the {@link EFragment} views are destroyed.
*/
VIEW_DESTROYED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.IgnoredWhenDetached;
import org.androidannotations.annotations.IgnoreWhen;
import org.androidannotations.annotations.ItemClick;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
Expand Down Expand Up @@ -58,7 +58,7 @@ void uiThread() {
}

@UiThread(propagation = UiThread.Propagation.REUSE)
@IgnoredWhenDetached
@IgnoreWhen(IgnoreWhen.State.DETACHED)
void uiThreadIgnored() {
didExecute = true;
}
Expand All @@ -74,16 +74,21 @@ void backgroundThread() {
}

@Background
@IgnoredWhenDetached
@IgnoreWhen(IgnoreWhen.State.DETACHED)
void backgroundThreadIgnored() {
didExecute = true;
}

@IgnoredWhenDetached
@IgnoreWhen(IgnoreWhen.State.DETACHED)
void ignored() {
didExecute = true;
}

@IgnoreWhen(IgnoreWhen.State.VIEW_DESTROYED)
void ignoreWhenViewDestroyed() {
didExecute = true;
}

void notIgnored() {
didExecute = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,46 @@ public void ignoredWhenDetachedWorksForIgnoredMethod() {
assertFalse(myListFragment.didExecute);
}

@Test
public void notIgnoredAfterOnCreateView() {
assertFalse(myListFragment.didExecute);
myListFragment.onCreateView(null, null, null);
assertFalse(myListFragment.didExecute);
myListFragment.ignoreWhenViewDestroyed();
assertTrue(myListFragment.didExecute);
}

@Test
public void ignoredWhenViewDestroyedForIgnoredMethod() {
assertFalse(myListFragment.didExecute);
myListFragment.onDestroyView();
myListFragment.ignoreWhenViewDestroyed();
assertFalse(myListFragment.didExecute);
}

@Test
public void notIgnoredAfterFragmentRecreate() {
assertFalse(myListFragment.didExecute);
myListFragment.onDestroyView();
myListFragment.onCreateView(null, null, null);
myListFragment.ignoreWhenViewDestroyed();
assertTrue(myListFragment.didExecute);
}

@Test
public void notIgnoredBeforeDetached() {
assertFalse(myListFragment.didExecute);
myListFragment.ignored();
assertTrue(myListFragment.didExecute);
}

@Test
public void notIgnoredBeforeViewDestroyed() {
assertFalse(myListFragment.didExecute);
myListFragment.ignoreWhenViewDestroyed();
assertTrue(myListFragment.didExecute);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need another test case here: call onDestroyView(), then onCreateView(). In that case the annotated method should not be ignored.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense. I will add it for onCreateView()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but i meant another thing:
destroyView
createView
callMethod
assert didExecute true

This is the case when a Fragment is returned from the back stack.
The current test is not that interesting, because basically it is the same as ignoredWhenViewDestroyedForIgnoredMethod.

You can just fix it without creating a separate commit.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, actually not the same as the other, but it is not testing that onCreateView does set the viewDestroyed field to true.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will add the test case.

I don't think onCreateView set viewDestroyed field to true

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worry.

I added more test case and squash. Check this method. https://github.com/excilys/androidannotations/pull/1664/files#diff-5474a5decd9ffab9908ae97c83444b47R143

In case you don't want me to commit & squash, let me know.

@Test
public void layoutNotInjectedWithoutForce() {
View buttonInInjectedLayout = myListFragment.getView().findViewById(R.id.conventionButton);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.androidannotations.holder;

import static com.helger.jcodemodel.JExpr.FALSE;
import static com.helger.jcodemodel.JExpr.TRUE;
import static com.helger.jcodemodel.JExpr._new;
import static com.helger.jcodemodel.JExpr._null;
import static com.helger.jcodemodel.JExpr._super;
Expand All @@ -23,6 +25,7 @@
import static com.helger.jcodemodel.JMod.PRIVATE;
import static com.helger.jcodemodel.JMod.PUBLIC;
import static com.helger.jcodemodel.JMod.STATIC;
import static com.helger.jcodemodel.JMod.VOLATILE;
import static org.androidannotations.helper.ModelConstants.generationSuffix;

import javax.lang.model.element.TypeElement;
Expand All @@ -46,6 +49,7 @@
public class EFragmentHolder extends EComponentWithViewSupportHolder implements HasInstanceState, HasOptionsMenu, HasOnActivityResult, HasReceiverRegistration, HasPreferences {

private JFieldVar contentView;
private JFieldVar viewDestroyedField;
private JBlock setContentViewBlock;
private JVar inflater;
private JVar container;
Expand Down Expand Up @@ -208,6 +212,19 @@ private void setContentView() {
contentView = generatedClass.field(PRIVATE, getClasses().VIEW, "contentView" + generationSuffix());
}

public JFieldVar getViewDestroyedField() {
if (viewDestroyedField == null) {
setViewDestroyedField();
}
return viewDestroyedField;
}

private void setViewDestroyedField() {
viewDestroyedField = generatedClass.field(PRIVATE | VOLATILE, getCodeModel().BOOLEAN, "viewDestroyed" + generationSuffix());
getSetContentViewBlock().assign(viewDestroyedField, FALSE);
getOnDestroyViewAfterSuperBlock().assign(viewDestroyedField, TRUE);
}

private void setOnCreateView() {
JMethod onCreateView = generatedClass.method(PUBLIC, getClasses().VIEW, "onCreateView");
onCreateView.annotate(Override.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
import org.androidannotations.internal.core.handler.HierarchyViewerSupportHandler;
import org.androidannotations.internal.core.handler.HtmlResHandler;
import org.androidannotations.internal.core.handler.HttpsClientHandler;
import org.androidannotations.internal.core.handler.IgnoredWhenDetachedHandler;
import org.androidannotations.internal.core.handler.IgnoreWhenHandler;
import org.androidannotations.internal.core.handler.InjectMenuHandler;
import org.androidannotations.internal.core.handler.InstanceStateHandler;
import org.androidannotations.internal.core.handler.ItemClickHandler;
Expand Down Expand Up @@ -206,7 +206,7 @@ public List<AnnotationHandler<?>> getHandlers(AndroidAnnotationsEnvironment andr
annotationHandlers.add(new PageScrollStateChangedHandler(androidAnnotationEnv));
annotationHandlers.add(new PageSelectedHandler(androidAnnotationEnv));

annotationHandlers.add(new IgnoredWhenDetachedHandler(androidAnnotationEnv));
annotationHandlers.add(new IgnoreWhenHandler(androidAnnotationEnv));

annotationHandlers.add(new AfterInjectHandler(androidAnnotationEnv));
annotationHandlers.add(new AfterExtrasHandler(androidAnnotationEnv));
Expand All @@ -231,7 +231,7 @@ public List<AnnotationHandler<?>> getHandlers(AndroidAnnotationsEnvironment andr

/*
* UIThreadHandler and BackgroundHandler must be after TraceHandler and
* IgnoredWhenDetached
* IgnoreWhen
*/
annotationHandlers.add(new UiThreadHandler(androidAnnotationEnv));
annotationHandlers.add(new BackgroundHandler(androidAnnotationEnv));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@

import org.androidannotations.AndroidAnnotationsEnvironment;
import org.androidannotations.ElementValidation;
import org.androidannotations.annotations.IgnoredWhenDetached;
import org.androidannotations.annotations.IgnoreWhen;
import org.androidannotations.handler.BaseAnnotationHandler;
import org.androidannotations.holder.EFragmentHolder;

import com.helger.jcodemodel.JBlock;
import com.helger.jcodemodel.JConditional;
import com.helger.jcodemodel.JMethod;

public class IgnoredWhenDetachedHandler extends BaseAnnotationHandler<EFragmentHolder> {
public class IgnoreWhenHandler extends BaseAnnotationHandler<EFragmentHolder> {

public IgnoredWhenDetachedHandler(AndroidAnnotationsEnvironment environment) {
super(IgnoredWhenDetached.class, environment);
public IgnoreWhenHandler(AndroidAnnotationsEnvironment environment) {
super(IgnoreWhen.class, environment);
}

@Override
Expand All @@ -53,6 +54,17 @@ public void process(Element element, EFragmentHolder holder) throws Exception {
JMethod delegatingMethod = codeModelHelper.overrideAnnotatedMethod(executableElement, holder);
JBlock previousMethodBody = codeModelHelper.removeBody(delegatingMethod);

delegatingMethod.body()._if(invoke(holder.getGeneratedClass().staticRef("this"), "getActivity").ne(_null()))._then().add(previousMethodBody);
IgnoreWhen ignoreWhen = element.getAnnotation(IgnoreWhen.class);
JBlock methodBody = delegatingMethod.body();
JConditional conditional = null;
switch (ignoreWhen.value()) {
case VIEW_DESTROYED:
conditional = methodBody._if(holder.getViewDestroyedField().not());
break;
case DETACHED:
conditional = methodBody._if(invoke(holder.getGeneratedClass().staticRef("this"), "getActivity").ne(_null()));
break;
}
conditional._then().add(previousMethodBody);
}
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.