This repository has been archived by the owner on Mar 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 101
Bugfix: Presenter not destroyed when Fragment is popped off the backstack #78
Merged
StefMa
merged 83 commits into
master
from
bugfix/fragment_backstack_presenter_not_destroyed
Apr 25, 2017
Merged
Changes from 62 commits
Commits
Show all changes
83 commits
Select commit
Hold shift + click to select a range
f0b5a3d
Adds a TiFragmentDelegateBuilder.
d482f01
Changes the visibility of the SAVED_PRESENTER_ID class variable in th…
b6e0f67
Adds a TiFragmentPresenterDestroyTest class with a first test impleme…
34b803e
Merge branch 'master' into bugfix/fragment_backstack_presenter_not_de…
c41603c
Inject savior with fragment delegate builder
81323af
Adds more tests to the TiFragmentPresenterDestroyTest class.
0f87776
Refactors method names in the TiFragmentDelegateBuilder class.
b1c9b70
Changes the back stack test case.
788f4c4
Adds a fragment lifecycle test to the sample application.
edf1db7
Logs delegate method callbacks in the TestFragment.
a7cac19
Changes tests according to the real Fragment lifecycle.
92b3c68
Adds more tests to the TiFragmentPresenterDestroyTest.
89c7a25
Change name of sample app
c957464
Add all test cases stubs
ccbb6c6
Moves the basic Bundle initialization into the setUp() method of the …
831fc34
Logs if onCreate_afterSuper should be called with null or with a non …
0758938
Adds an option to retain a fragment instance in the FragmentLifecycle…
c9557c0
Improves logging in the TestFragment.
04179dc
Implements all tests for the combination savior = false and retain = …
4ff89db
Fixes false test implementations.
803b7b3
Add HostingActivity which can change it’s state of isChangingConfigur…
1f32468
Fixes test cases so they only test the scope that is implied by the t…
1a8b791
Adds more test case implementations.
c5f831d
Adds missing test implementations.
2497ca7
Improve logging
5dda802
Splits the tests into multiple files.
fd16f88
Adds more missing test cases.
05f2541
Adds more missing test cases.
838ab48
Implement equals correctly for the configuration
ea700d8
Add more logging
8c0df9c
Verified and improved the single fragment default cases
6e3476e
Verify retain false tests with savior true for single fragments
ac09f78
Improve logging
1821b6d
Verify dontKeepActivitiesFalse_activityFinishing tests
0c1c340
Verify saviorFalse_retainFalse_dontKeepActivitiesFalse_activityChangi…
423d886
Adjust comments and rename HostingActivity reset function
ec3d582
Verify first dontKeepActivitiesFalse cases
f82dc45
Finish verifying Single Fragment cases
b5dd9e7
Add moveToBackground_moveToForeground tests
81a81be
Add more move to background -> foreground cases
7efab6b
Add more move to background -> foreground cases
549bce8
Finalize moveToBackground -> moveToForeground tests
ac569f5
Mark default cases for muti fragment tests
95958ff
Rename “Default case” to “Default config”
8c4d7a2
Changes code formatting.
65f601b
Allow removing FragmentA
8e2de39
Move don’t keep Activities cases to a sparate file
49ffd78
Merge branch 'master' into bugfix/fragment_backstack_presenter_not_de…
7bf7910
Remove verification comments because all test have to be rechecked an…
0ac8f79
Future TiFragments use the savior or don’t retain. savior false but r…
178f9f3
Allow set Fragment#isRemoving in tests
5daf108
Add don’t keep activities tests
e01d246
Remove savior=false tests, savior false is deprecated
88f2985
Finish all current fragment tests
bfc8a2d
Also remove static savior setting in Activity
23c41a5
Observe activity scopes and destory presenters accordingly
00dc083
Make PresenterSavior testable
a758265
Fix recursive call
4e71f20
Remove deprecated android tests, replaced with far better jvm tests
7ab1143
Harden providePresenter() to only return INITIALIZED state instances
6dfa2ca
Print the current presenter state when failing
b5a0281
Create a new Presenter when the Presenter is destroyed
b767f63
Extract ActivityLifecycleCallbacks to a separate class
933e215
Move methods for testing to a TestPresenterSavior class
f10f606
Make fragment presenter retain adjustable
096444e
Add mulitple variants for the previous presenter leaking case
a8b6c61
Test to reuse of fragments
52e02c6
Remove todo which is now done
96c5f93
Cleanup logging
f49152a
Remove all deprecated usages of setUseStaticSaviorToRetain()
e46621e
Add documentation
3fac777
Don’t allow the usage of setRetainInstance(true)
a6dbf0d
Simplify destroy logic in TiFragment and TiActivity
c3997c8
Rename isInBackstack -> isFragmentInBackstack
191bb5d
Improve providePresenter documentation
6d67cbf
Remove unused class (was moved to sample)
ab8f873
Review improvements
9cd36cb
Add detach/attach feature to sample
43aa76a
Don’t print a hint as warning
a89f8de
Use same visibility for Listener as the using class
cf4d1d4
Add sample/test for viewpager
StefMa 143a378
Better starting of Activities
StefMa 3880e06
Merge pull request #84 from StefMa/bugfix/fragment_backstack_presente…
passsy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
197 changes: 197 additions & 0 deletions
197
.../java/net/grandcentrix/thirtyinch/sample/fragmentlifecycle/FragmentLifecycleActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
package net.grandcentrix.thirtyinch.sample.fragmentlifecycle; | ||
|
||
import net.grandcentrix.thirtyinch.sample.R; | ||
|
||
import android.os.Bundle; | ||
import android.provider.Settings; | ||
import android.support.v4.app.Fragment; | ||
import android.support.v4.app.FragmentManager; | ||
import android.support.v4.app.FragmentTransaction; | ||
import android.support.v7.app.AppCompatActivity; | ||
import android.support.v7.widget.SwitchCompat; | ||
import android.util.Log; | ||
import android.view.View; | ||
import android.widget.TextView; | ||
|
||
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES; | ||
import static net.grandcentrix.thirtyinch.sample.fragmentlifecycle.TestFragment.testFragmentInstanceCount; | ||
|
||
public class FragmentLifecycleActivity extends AppCompatActivity { | ||
|
||
static int fragmentLifecycleActivityInstanceCount = -1; | ||
|
||
private final String TAG = this.getClass().getSimpleName() | ||
+ "@" + Integer.toHexString(this.hashCode()); | ||
|
||
private SwitchCompat mSwitchAddToBackStack; | ||
|
||
private SwitchCompat mSwitchRetainFragmentInstance; | ||
|
||
public void addFragmentA(View view) { | ||
final TestFragmentA fragment = new TestFragmentA(); | ||
Log.v(TAG, "adding FragmentA"); | ||
addFragment(fragment); | ||
} | ||
|
||
public void addFragmentB(View view) { | ||
final TestFragmentB fragment = new TestFragmentB(); | ||
Log.v(TAG, "adding FragmentB"); | ||
addFragment(fragment); | ||
} | ||
|
||
@Override | ||
public void finish() { | ||
super.finish(); | ||
Log.v(TAG, "// When the Activity finishes"); | ||
} | ||
|
||
public void finishActivity(View view) { | ||
finish(); | ||
} | ||
|
||
@Override | ||
public void onBackPressed() { | ||
Log.v(TAG, "// When the back button gets pressed"); | ||
Log.v(TAG, "// When the top most fragment gets popped"); | ||
final FragmentManager fragmentManager = getSupportFragmentManager(); | ||
if (fragmentManager.getBackStackEntryCount() > 0) { | ||
fragmentManager.popBackStack(); | ||
} else { | ||
super.onBackPressed(); | ||
} | ||
} | ||
|
||
public void recreateActivity(View view) { | ||
Log.v(TAG, "// And when the Activity is changing its configurations."); | ||
recreate(); | ||
} | ||
|
||
public void removeFragmentA(View view) { | ||
final Fragment fragment = getSupportFragmentManager() | ||
.findFragmentById(R.id.fragment_placeholder); | ||
if (fragment instanceof TestFragmentA) { | ||
getSupportFragmentManager().beginTransaction() | ||
.remove(fragment) | ||
.commitNow(); | ||
} | ||
} | ||
|
||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
if (savedInstanceState == null) { | ||
//started for the first time, reset all counters | ||
fragmentLifecycleActivityInstanceCount = -1; | ||
TestFragment.testFragmentInstanceCount = -1; | ||
} | ||
|
||
fragmentLifecycleActivityInstanceCount++; | ||
setContentView(R.layout.activity_fragment_lifecycle); | ||
FragmentManager.enableDebugLogging(true); | ||
Log.v(TAG, "onCreate of " + this); | ||
|
||
mSwitchAddToBackStack = (SwitchCompat) findViewById(R.id.switch_add_back_stack); | ||
mSwitchRetainFragmentInstance = (SwitchCompat) findViewById( | ||
R.id.switch_retain_fragment_instance); | ||
final TextView textDontKeepActivities = (TextView) findViewById( | ||
R.id.text_dont_keep_activities); | ||
textDontKeepActivities.setText( | ||
isDontKeepActivities() ? R.string.dont_keep_activities_enabled | ||
: R.string.dont_keep_activities_disabled); | ||
|
||
Log.v(TAG, "// A new Activity gets created by the Android Framework."); | ||
Log.v(TAG, "final HostingActivity hostingActivity" + fragmentLifecycleActivityInstanceCount | ||
+ " = new HostingActivity();"); | ||
} | ||
|
||
@Override | ||
protected void onDestroy() { | ||
super.onDestroy(); | ||
|
||
Log.v(TAG, "onDestroy of " + this); | ||
|
||
Log.v(TAG, "hostingActivity" + fragmentLifecycleActivityInstanceCount | ||
+ ".setChangingConfiguration(" + isChangingConfigurations() + ");"); | ||
Log.v(TAG, "hostingActivity" + fragmentLifecycleActivityInstanceCount | ||
+ ".setFinishing(" + isFinishing() + ");"); | ||
Log.v(TAG, "// hostingActivity" + fragmentLifecycleActivityInstanceCount | ||
+ " got destroyed."); | ||
} | ||
|
||
@Override | ||
protected void onPause() { | ||
super.onPause(); | ||
Log.d(TAG, "onPause()"); | ||
Log.v(TAG, "hostingActivity" + fragmentLifecycleActivityInstanceCount + "" | ||
+ ".setChangingConfiguration(" + isChangingConfigurations() + ");"); | ||
Log.v(TAG, "hostingActivity" + fragmentLifecycleActivityInstanceCount + "" | ||
+ ".setFinishing(" + isFinishing() + ");"); | ||
} | ||
|
||
@Override | ||
protected void onSaveInstanceState(final Bundle outState) { | ||
super.onSaveInstanceState(outState); | ||
Log.d(TAG, "onSaveInstanceState(Bundle)"); | ||
Log.v(TAG, "hostingActivity" + fragmentLifecycleActivityInstanceCount + "" | ||
+ ".setChangingConfiguration(" + isChangingConfigurations() + ");"); | ||
Log.v(TAG, "hostingActivity" + fragmentLifecycleActivityInstanceCount + "" | ||
+ ".setFinishing(" + isFinishing() + ");"); | ||
} | ||
|
||
private void addFragment(final Fragment fragment) { | ||
final FragmentManager fragmentManager = getSupportFragmentManager(); | ||
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); | ||
if (isRetainFragmentInstance()) { | ||
Log.v(TAG, "retaining fragment instance"); | ||
fragment.setRetainInstance(true); | ||
} | ||
fragmentTransaction.replace(R.id.fragment_placeholder, fragment); | ||
if (isAddToBackStack()) { | ||
Log.v(TAG, "adding transaction to the back stack"); | ||
fragmentTransaction.addToBackStack(null); | ||
} | ||
final int backStackId = fragmentTransaction.commit(); | ||
Log.v(TAG, "\n// Given a Presenter ..."); | ||
// (testFragmentInstanceCount + 1) because it will be created after executing this code | ||
Log.v(TAG, "final TestPresenter presenter" + (testFragmentInstanceCount + 1) + " =" | ||
+ " new TestPresenter(new TiConfiguration.Builder()\n" | ||
+ " .setUseStaticSaviorToRetain(/*TODO set*/)\n" | ||
+ " .setRetainPresenterEnabled(" + isRetainFragmentInstance() + ")\n" | ||
+ " .build());"); | ||
|
||
Log.v(TAG, "\n// And given a Fragment."); | ||
Log.v(TAG, "final TiFragmentDelegate<TiPresenter<TiView>, TiView> " | ||
+ "delegate" + (testFragmentInstanceCount + 1) + "\n" | ||
+ " = new TiFragmentDelegateBuilder()\n" | ||
+ " .setDontKeepActivitiesEnabled(" + isDontKeepActivities() + ")\n" | ||
+ " .setHostingActivity(hostingActivity)\n" | ||
+ " .setSavior(mSavior)\n" | ||
+ " .setPresenter(presenter" + (testFragmentInstanceCount + 1) | ||
+ ")\n" | ||
+ " .build();"); | ||
|
||
if (backStackId >= 0) { | ||
Log.v(TAG, "Back stack ID: " + String.valueOf(backStackId)); | ||
} | ||
} | ||
|
||
private boolean isAddToBackStack() { | ||
return mSwitchAddToBackStack.isChecked(); | ||
} | ||
|
||
private boolean isDontKeepActivities() { | ||
// default behaviour | ||
int dontKeepActivities = 0; | ||
try { | ||
dontKeepActivities = Settings.Global | ||
.getInt(getContentResolver(), ALWAYS_FINISH_ACTIVITIES); | ||
} catch (Settings.SettingNotFoundException e) { | ||
e.printStackTrace(); | ||
} | ||
return dontKeepActivities != 0; | ||
} | ||
|
||
private boolean isRetainFragmentInstance() { | ||
return mSwitchRetainFragmentInstance.isChecked(); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use your util here now. Otherwise
AndroidDeveloperOptions
is not used and can removed