0

I am reflecting on some code I read in this article https://github.com/frogermcs/GithubClient/tree/1bf53a2a36c8a85435e877847b987395e482ab4a

BaseActivity.java:

public abstract class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupActivityComponent();
    }

    protected abstract void setupActivityComponent();
}

SplashActivityModule.java:

@Module
public class SplashActivityModule {
    private SplashActivity splashActivity;

    public SplashActivityModule(SplashActivity splashActivity) {
        this.splashActivity = splashActivity;
    }

    @Provides
    @ActivityScope
    SplashActivity provideSplashActivity() {
        return splashActivity;
    }

    @Provides
    @ActivityScope
    SplashActivityPresenter
    provideSplashActivityPresenter(Validator validator, UserManager 
    userManager, HeavyLibraryWrapper heavyLibraryWrapper) {
        return new SplashActivityPresenter(splashActivity, validator, 
                                           userManager, heavyLibraryWrapper);
    }
}

SplashActivityPresenter is injected inside SplashActivity.java:

public class SplashActivity extends BaseActivity {
    ...

    @Inject
    SplashActivityPresenter presenter;

    @Override
    protected void setupActivityComponent() {
        GithubClientApplication.get(this)
                .getAppComponent()
                .plus(new SplashActivityModule(this))
                .inject(this);
    }

SplashActivityPresenter.java:

public class SplashActivityPresenter {
    public String username;

    private SplashActivity splashActivity;
    private Validator validator;
    private UserManager userManager;
    private HeavyLibraryWrapper heavyLibraryWrapper;

    public SplashActivityPresenter(SplashActivity splashActivity, 
        Validator validator, UserManager userManager, 
        HeavyLibraryWrapper heavyLibraryWrapper) {
        this.splashActivity = splashActivity;
        this.validator = validator;
        this.userManager = userManager;
            this.heavyLibraryWrapper = heavyLibraryWrapper;

        //This calls should be delivered to ExternalLibrary right after it will be initialized
        this.heavyLibraryWrapper.callMethod();
        this.heavyLibraryWrapper.callMethod();
        this.heavyLibraryWrapper.callMethod();
        this.heavyLibraryWrapper.callMethod();
    }

    public void onShowRepositoriesClick() {
        if (validator.validUsername(username)) {
            splashActivity.showLoading(true);
            userManager.getUser(username).subscribe(new 
SimpleObserver<User>() {
                @Override
                public void onNext(User user) {
                    splashActivity.showLoading(false);
                    splashActivity.showRepositoriesListForUser(user);
                }

                @Override
                public void onError(Throwable e) {
                    splashActivity.showLoading(false);
                    splashActivity.showValidationError();
                }
            });
        } else {
            splashActivity.showValidationError();
        }
    }
}
  1. Why scope the view to the activity? Suppose we did not scope it. The view is held onto by the presenter. Once the activity finishes, there is no way to access the presenter so it is eligible for garbage collection. Transitively the view reference would also be eligible for garbage collection, right?

  2. Why scope the presenter to the activity? Suppose we did not scope it. The activity creates a new presenter for each activity instance(each time you first enter the activity, or rotate the screen). Once the activity finishes, there is no way to access the presenter so it is eligible for garbage collection.

What is the harm in leaving the view and presenter unscoped? Is there a way for me to test the benefits of the scoping against unscoping?

HukeLau_DABA
  • 2,384
  • 6
  • 33
  • 51

1 Answers1

0

This answer may not be perfect. but it can help you to understand more.
-here is when an object is eligible for garbage collection.
-if we do not scope activity and presenter. we might end in a dead lock for garbage collection. where activity holds reference to presenter and presenter holds activity reference.
-two main issues i see there

1. Context leakage
2. Out of memory(Rare case.)
1) When context leakage occurs activity finished and you wanna do something update to that activity.(when you don't release presenter).
suppose SimpleObserver's onNext is called after activity finished. it will run in to errors. so some how you need to release activity's reference.(just assign null in method onDestroy.)
2) activity and presenter holding each other references it will never be garbage collected until application is killed. so you may run out of memory.

Amit Goswami
  • 314
  • 2
  • 11
  • If you don't put the Activity/Fragment on an object graph with a greater scope than their lifetime, then it won't leak its context. If Activity/Fragment unregisters itself in `onDestroy`/`onDestroyView` (respectively), then it also won't leak the context. – EpicPandaForce Mar 26 '19 at 13:44