Skip to content

Commit cf6becd

Browse files
committed
Improved implementation
1 parent 8e8dee6 commit cf6becd

File tree

10 files changed

+168
-127
lines changed

10 files changed

+168
-127
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ android:
44
components:
55
- platform-tools
66
- tools
7-
- android-23
8-
- build-tools-23.0.3
7+
- android-24
8+
- build-tools-24.0.0
99
- extra-android-m2repository
1010
- extra-android-support
1111

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ Change Log
22
==========
33

44

5+
## Version 1.1.0
6+
7+
_2016-07-07_
8+
9+
Improved implementation.
10+
11+
512
## Version 1.0.0
613

714
_2016-05-26_

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Implementation of the multiple back stacks. Using this library allows implementa
1515
Compatibility
1616
-------------
1717

18-
This library is compatible from API 7 (Android 2.1).
18+
This library is compatible from API 9 (Android 2.3).
1919

2020

2121
Download
@@ -36,7 +36,7 @@ Add the dependency
3636

3737
```groovy
3838
dependencies {
39-
compile 'com.github.jetradarmobile:multibackstack:1.0.0'
39+
compile 'com.github.jetradarmobile:multibackstack:1.1.0'
4040
}
4141
```
4242

multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/MainActivity.java

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -30,54 +30,67 @@
3030
import static com.ashokvarma.bottomnavigation.BottomNavigationBar.OnTabSelectedListener;
3131

3232
public class MainActivity extends BackStackActivity implements OnTabSelectedListener {
33-
private static final String STATE_TAB_ID = "tab_id";
33+
private static final String STATE_CURRENT_TAB_ID = "current_tab_id";
3434
private static final int MAIN_TAB_ID = 0;
3535

36-
private BottomNavigationBar bottomNavigationBar;
36+
private BottomNavigationBar bottomNavBar;
3737
private Fragment curFragment;
3838
private int curTabId;
3939

4040
@Override
4141
protected void onCreate(Bundle state) {
4242
super.onCreate(state);
4343
setContentView(R.layout.activity_main);
44-
setUpBottomNavigationBar();
44+
setUpBottomNavBar();
45+
46+
if (state == null) {
47+
bottomNavBar.selectTab(MAIN_TAB_ID, false);
48+
showFragment(rootTabFragment(MAIN_TAB_ID));
49+
}
4550
}
4651

47-
private void setUpBottomNavigationBar() {
48-
bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation);
49-
bottomNavigationBar
52+
private void setUpBottomNavBar() {
53+
bottomNavBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation);
54+
bottomNavBar
5055
.addItem(new BottomNavigationItem(R.drawable.ic_search_24dp, R.string.search))
51-
.addItem(new BottomNavigationItem(R.drawable.ic_favorite_24dp, R.string.favorite))
56+
.addItem(new BottomNavigationItem(R.drawable.ic_favorite_24dp, R.string.favorites))
5257
.addItem(new BottomNavigationItem(R.drawable.ic_profile_24dp, R.string.profile))
5358
.initialise();
59+
bottomNavBar.setTabSelectedListener(this);
60+
}
5461

55-
bottomNavigationBar.setTabSelectedListener(this);
56-
if (getSupportFragmentManager().findFragmentById(R.id.content) == null) {
57-
bottomNavigationBar.selectTab(MAIN_TAB_ID, false);
58-
showFragment(fragmentByTab(MAIN_TAB_ID));
62+
@NonNull
63+
private Fragment rootTabFragment(int tabId) {
64+
switch (tabId) {
65+
case 0:
66+
return ItemListFragment.newInstance(getString(R.string.search));
67+
case 1:
68+
return ItemListFragment.newInstance(getString(R.string.favorites));
69+
case 2:
70+
return ItemListFragment.newInstance(getString(R.string.profile));
71+
default:
72+
throw new IllegalArgumentException();
5973
}
6074
}
6175

6276
@Override
6377
protected void onRestoreInstanceState(Bundle savedInstanceState) {
6478
super.onRestoreInstanceState(savedInstanceState);
6579
curFragment = getSupportFragmentManager().findFragmentById(R.id.content);
66-
curTabId = savedInstanceState.getInt(STATE_TAB_ID);
67-
bottomNavigationBar.selectTab(curTabId, false);
80+
curTabId = savedInstanceState.getInt(STATE_CURRENT_TAB_ID);
81+
bottomNavBar.selectTab(curTabId, false);
6882
}
6983

7084
@Override
7185
protected void onSaveInstanceState(Bundle outState) {
72-
outState.putInt(STATE_TAB_ID, curTabId);
86+
outState.putInt(STATE_CURRENT_TAB_ID, curTabId);
7387
super.onSaveInstanceState(outState);
7488
}
7589

76-
@SuppressWarnings("ConstantConditions")
7790
@Override
7891
public void onBackPressed() {
79-
if (!backStackManager.empty()) {
80-
Pair<Integer, Fragment> pair = popFromBackStack();
92+
Pair<Integer, Fragment> pair = popFragmentFromBackStack();
93+
if (pair != null) {
8194
backTo(pair.first, pair.second);
8295
} else {
8396
super.onBackPressed();
@@ -87,14 +100,14 @@ public void onBackPressed() {
87100
@Override
88101
public void onTabSelected(int position) {
89102
if (curFragment != null) {
90-
pushToBackStack(curTabId, curFragment);
103+
pushFragmentToBackStack(curTabId, curFragment);
91104
}
92105
curTabId = position;
93-
curFragment = popFromBackStack(curTabId);
94-
if (curFragment == null) {
95-
curFragment = fragmentByTab(curTabId);
106+
Fragment fragment = popFragmentFromBackStack(curTabId);
107+
if (fragment == null) {
108+
fragment = rootTabFragment(curTabId);
96109
}
97-
replaceFragment(curFragment);
110+
replaceFragment(fragment);
98111
}
99112

100113
@Override
@@ -105,55 +118,45 @@ public void onTabReselected(int position) {
105118
@Override
106119
public void onTabUnselected(int position) {}
107120

108-
private Fragment fragmentByTab(int tabId) {
109-
switch (tabId) {
110-
case 0:
111-
return ItemListFragment.newInstance(getString(R.string.search));
112-
case 1:
113-
return ItemListFragment.newInstance(getString(R.string.favorite));
114-
case 2:
115-
return ItemListFragment.newInstance(getString(R.string.profile));
116-
default:
117-
throw new IllegalArgumentException();
118-
}
119-
}
120-
121121
public void showFragment(@NonNull Fragment fragment) {
122122
showFragment(fragment, true);
123123
}
124124

125125
public void showFragment(@NonNull Fragment fragment, boolean addToBackStack) {
126126
if (curFragment != null && addToBackStack) {
127-
pushToBackStack(curTabId, curFragment);
127+
pushFragmentToBackStack(curTabId, curFragment);
128128
}
129-
curFragment = fragment;
130129
replaceFragment(fragment);
131130
}
132131

133132
private void backTo(int tabId, @NonNull Fragment fragment) {
134-
curTabId = tabId;
135-
bottomNavigationBar.selectTab(curTabId, false);
136-
curFragment = fragment;
133+
if (tabId != curTabId) {
134+
curTabId = tabId;
135+
bottomNavBar.selectTab(curTabId, false);
136+
}
137137
replaceFragment(fragment);
138138
getSupportFragmentManager().executePendingTransactions();
139139
}
140140

141141
private void backToRoot() {
142-
Fragment originalRootFragment = fragmentByTab(curTabId);
143-
if (curFragment.getClass() != originalRootFragment.getClass()) {
144-
Fragment rootFragment = popRootFromBackStack(curTabId);
145-
if (rootFragment == null || rootFragment.getClass() != originalRootFragment.getClass()) {
146-
rootFragment = originalRootFragment;
147-
}
148-
curFragment = rootFragment;
149-
replaceFragment(rootFragment);
142+
if (isRootTabFragment(curFragment, curTabId)) {
143+
return;
150144
}
145+
resetBackStackToRoot(curTabId);
146+
Fragment rootFragment = popFragmentFromBackStack(curTabId);
147+
assert rootFragment != null;
148+
backTo(curTabId, rootFragment);
149+
}
150+
151+
private boolean isRootTabFragment(@NonNull Fragment fragment, int tabId) {
152+
return fragment.getClass() == rootTabFragment(tabId).getClass();
151153
}
152154

153155
private void replaceFragment(@NonNull Fragment fragment) {
154156
FragmentManager fm = getSupportFragmentManager();
155157
FragmentTransaction tr = fm.beginTransaction();
156158
tr.replace(R.id.content, fragment);
157-
tr.commit();
159+
tr.commitAllowingStateLoss();
160+
curFragment = fragment;
158161
}
159162
}

multibackstack-sample/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
<string name="app_name">MultiBackStack</string>
33

44
<string name="search">Search</string>
5-
<string name="favorite">Favorite</string>
5+
<string name="favorites">Favorites</string>
66
<string name="profile">Profile</string>
77
</resources>

multibackstack/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ android {
55
buildToolsVersion rootProject.ext.buildToolsVersion
66

77
defaultConfig {
8-
minSdkVersion 7
8+
minSdkVersion 9
99
}
1010
}
1111

multibackstack/src/main/java/com/jetradar/multibackstack/BackStack.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,23 @@
2525

2626
public class BackStack implements Parcelable {
2727
public final int hostId;
28-
private final Stack<BackStackEntry> stack;
28+
private final Stack<BackStackEntry> entriesStack = new Stack<>();
2929

3030
public BackStack(int hostId) {
3131
this.hostId = hostId;
32-
stack = new Stack<>();
3332
}
3433

3534
public void push(@NonNull BackStackEntry entry) {
36-
stack.push(entry);
35+
entriesStack.push(entry);
3736
}
3837

3938
@Nullable
4039
public BackStackEntry pop() {
41-
return empty() ? null : stack.pop();
40+
return empty() ? null : entriesStack.pop();
4241
}
4342

4443
public boolean empty() {
45-
return stack.empty();
44+
return entriesStack.empty();
4645
}
4746

4847
@Override
@@ -53,19 +52,18 @@ public int describeContents() {
5352
@Override
5453
public void writeToParcel(Parcel out, int flags) {
5554
out.writeInt(hostId);
56-
int len = stack.size();
57-
out.writeInt(len);
58-
for (int i = 0; i < len; i++) {
59-
stack.get(i).writeToParcel(out, flags);
55+
int size = entriesStack.size();
56+
out.writeInt(size);
57+
for (int i = 0; i < size; i++) {
58+
entriesStack.get(i).writeToParcel(out, flags);
6059
}
6160
}
6261

6362
private BackStack(Parcel in) {
6463
hostId = in.readInt();
65-
int len = in.readInt();
66-
stack = new Stack<>();
67-
for (int i = 0; i < len; i++) {
68-
stack.push(BackStackEntry.CREATOR.createFromParcel(in));
64+
int size = in.readInt();
65+
for (int i = 0; i < size; i++) {
66+
entriesStack.push(BackStackEntry.CREATOR.createFromParcel(in));
6967
}
7068
}
7169

multibackstack/src/main/java/com/jetradar/multibackstack/BackStackActivity.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import android.util.Log;
2626

2727
public abstract class BackStackActivity extends AppCompatActivity {
28-
private static final String STATE_BACK_STACK = "back_stack";
28+
private static final String STATE_BACK_STACK_MANAGER = "back_stack_manager";
2929

3030
protected BackStackManager backStackManager;
3131

@@ -44,16 +44,16 @@ protected void onDestroy() {
4444
@Override
4545
protected void onSaveInstanceState(Bundle outState) {
4646
super.onSaveInstanceState(outState);
47-
outState.putParcelable(STATE_BACK_STACK, backStackManager.saveState());
47+
outState.putParcelable(STATE_BACK_STACK_MANAGER, backStackManager.saveState());
4848
}
4949

5050
@Override
5151
protected void onRestoreInstanceState(Bundle savedInstanceState) {
5252
super.onRestoreInstanceState(savedInstanceState);
53-
backStackManager.restoreState(savedInstanceState.getParcelable(STATE_BACK_STACK));
53+
backStackManager.restoreState(savedInstanceState.getParcelable(STATE_BACK_STACK_MANAGER));
5454
}
5555

56-
protected boolean pushToBackStack(int hostId, @NonNull Fragment fragment) {
56+
protected boolean pushFragmentToBackStack(int hostId, @NonNull Fragment fragment) {
5757
try {
5858
BackStackEntry entry = BackStackEntry.create(getSupportFragmentManager(), fragment);
5959
backStackManager.push(hostId, entry);
@@ -65,20 +65,22 @@ protected boolean pushToBackStack(int hostId, @NonNull Fragment fragment) {
6565
}
6666

6767
@Nullable
68-
protected Fragment popFromBackStack(int hostId) {
68+
protected Fragment popFragmentFromBackStack(int hostId) {
6969
BackStackEntry entry = backStackManager.pop(hostId);
7070
return entry != null ? entry.toFragment(this) : null;
7171
}
7272

7373
@Nullable
74-
protected Pair<Integer, Fragment> popFromBackStack() {
74+
protected Pair<Integer, Fragment> popFragmentFromBackStack() {
7575
Pair<Integer, BackStackEntry> pair = backStackManager.pop();
7676
return pair != null ? Pair.create(pair.first, pair.second.toFragment(this)) : null;
7777
}
7878

79-
@Nullable
80-
protected Fragment popRootFromBackStack(int hostId) {
81-
BackStackEntry entry = backStackManager.popRoot(hostId);
82-
return entry != null ? entry.toFragment(this) : null;
79+
protected boolean resetBackStackToRoot(int hostId) {
80+
return backStackManager.resetToRoot(hostId);
81+
}
82+
83+
protected boolean clearBackStack(int hostId) {
84+
return backStackManager.clear(hostId);
8385
}
8486
}

multibackstack/src/main/java/com/jetradar/multibackstack/BackStackEntry.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
import android.support.v4.app.FragmentManager;
2828

2929
public class BackStackEntry implements Parcelable {
30-
private final String fname;
31-
private final SavedState state;
32-
private final Bundle args;
30+
public final String fname;
31+
public final SavedState state;
32+
public final Bundle args;
3333

3434
public BackStackEntry(@NonNull String fname, @Nullable SavedState state, @Nullable Bundle args) {
3535
this.fname = fname;

0 commit comments

Comments
 (0)