From 62a83dae5bc073cabaf3fa2b29d36682d2035a41 Mon Sep 17 00:00:00 2001 From: David Johannot Date: Tue, 29 Jan 2019 15:02:12 +0400 Subject: [PATCH] update library and sample to androidX + update the bottombar version that is also androidX compatible --- build.gradle | 14 +- gradle.properties | 5 +- gradle/wrapper/gradle-wrapper.properties | 4 +- multibackstack-sample/build.gradle | 6 +- .../multibackstack/sample/ItemFragment.java | 88 ++--- .../sample/ItemListFragment.java | 88 ++--- .../multibackstack/sample/MainActivity.java | 236 ++++++------- .../src/main/res/values/styles.xml | 5 - multibackstack/build.gradle | 2 +- .../jetradar/multibackstack/BackStack.java | 104 +++--- .../multibackstack/BackStackActivity.java | 139 ++++---- .../multibackstack/BackStackEntry.java | 159 ++++----- .../multibackstack/BackStackManager.java | 329 +++++++++--------- 13 files changed, 594 insertions(+), 585 deletions(-) diff --git a/build.gradle b/build.gradle index 556b8a4..af6f948 100644 --- a/build.gradle +++ b/build.gradle @@ -1,25 +1,27 @@ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:3.3.0' } } allprojects { repositories { + google() jcenter() } } ext { - compileSdkVersion = 25 - buildToolsVersion = '25.0.3' + compileSdkVersion = 28 + buildToolsVersion = '28.0.3' - supportDesign = 'com.android.support:design:25.3.1' - supportAppCompat = 'com.android.support:appcompat-v7:25.3.1' - bottomNavigationBar = 'com.ashokvarma.android:bottom-navigation-bar:1.4.1' + supportDesign = 'com.google.android.material:material:1.0.0-rc01' + supportAppCompat = 'androidx.appcompat:appcompat:1.0.0' + bottomNavigationBar = 'com.ashokvarma.android:bottom-navigation-bar:2.1.0' } task clean(type: Delete) { diff --git a/gradle.properties b/gradle.properties index 1d3591c..ccb748f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,7 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true + +android.useAndroidX=true +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d2688b9..900bf43 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Jan 08 22:38:21 MSK 2017 +#Tue Jan 29 14:32:25 GST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/multibackstack-sample/build.gradle b/multibackstack-sample/build.gradle index a27f2d6..281ebf5 100644 --- a/multibackstack-sample/build.gradle +++ b/multibackstack-sample/build.gradle @@ -1,9 +1,9 @@ apply plugin: 'com.android.application' dependencies { - compile project(':multibackstack') - compile rootProject.ext.supportDesign - compile rootProject.ext.bottomNavigationBar + implementation project(':multibackstack') + implementation rootProject.ext.supportDesign + implementation rootProject.ext.bottomNavigationBar } android { diff --git a/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemFragment.java b/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemFragment.java index 44a8fc4..ccef2d5 100644 --- a/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemFragment.java +++ b/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemFragment.java @@ -17,64 +17,66 @@ package com.jetradar.multibackstack.sample; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v7.app.ActionBar; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.fragment.app.Fragment; + public class ItemFragment extends Fragment { - private static final String ARG_ITEM = "item"; + private static final String ARG_ITEM = "item"; - private String item; + private String item; - public ItemFragment() {} + public ItemFragment() { + } - public static ItemFragment newInstance(String item) { - ItemFragment fragment = new ItemFragment(); - Bundle args = new Bundle(); - args.putString(ARG_ITEM, item); - fragment.setArguments(args); - return fragment; - } + public static ItemFragment newInstance(String item) { + ItemFragment fragment = new ItemFragment(); + Bundle args = new Bundle(); + args.putString(ARG_ITEM, item); + fragment.setArguments(args); + return fragment; + } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - item = getArguments().getString(ARG_ITEM); - } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + item = getArguments().getString(ARG_ITEM); + } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_item, container, false); - } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_item, container, false); + } - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - setUpActionBar(); + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + setUpActionBar(); - TextView textView = (TextView) view.findViewById(R.id.text); - textView.setText(item); - } + TextView textView = (TextView) view.findViewById(R.id.text); + textView.setText(item); + } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getActivity().onBackPressed(); - return true; + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + getActivity().onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); } - return super.onOptionsItemSelected(item); - } - @SuppressWarnings("ConstantConditions") - private void setUpActionBar() { - ActionBar actionBar = ((MainActivity) getActivity()).getSupportActionBar(); - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setTitle(item); - setHasOptionsMenu(true); - } + @SuppressWarnings("ConstantConditions") + private void setUpActionBar() { + ActionBar actionBar = ((MainActivity) getActivity()).getSupportActionBar(); + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setTitle(item); + setHasOptionsMenu(true); + } } \ No newline at end of file diff --git a/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemListFragment.java b/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemListFragment.java index a60cfd5..380da72 100644 --- a/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemListFragment.java +++ b/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/ItemListFragment.java @@ -17,9 +17,6 @@ package com.jetradar.multibackstack.sample; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.ListFragment; -import android.support.v7.app.ActionBar; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; @@ -27,55 +24,60 @@ import java.util.ArrayList; import java.util.List; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.fragment.app.ListFragment; + public class ItemListFragment extends ListFragment { - private static final String ARG_SECTION = "section"; + private static final String ARG_SECTION = "section"; - private List items; + private List items; - public ItemListFragment() {} + public ItemListFragment() { + } - public static ItemListFragment newInstance(String section) { - ItemListFragment fragment = new ItemListFragment(); - Bundle args = new Bundle(); - args.putString(ARG_SECTION, section); - fragment.setArguments(args); - return fragment; - } + public static ItemListFragment newInstance(String section) { + ItemListFragment fragment = new ItemListFragment(); + Bundle args = new Bundle(); + args.putString(ARG_SECTION, section); + fragment.setArguments(args); + return fragment; + } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - String section = getArguments().getString(ARG_SECTION); - items = createItemsForSection(section); - } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + String section = getArguments().getString(ARG_SECTION); + items = createItemsForSection(section); + } - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - setUpActionBar(); + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setUpActionBar(); - ArrayAdapter adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, items); - setListAdapter(adapter); - } + ArrayAdapter adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, items); + setListAdapter(adapter); + } - @Override - public void onListItemClick(ListView l, View v, int position, long id) { - ((MainActivity) getActivity()).showFragment(ItemFragment.newInstance(items.get(position))); - } + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + ((MainActivity) getActivity()).showFragment(ItemFragment.newInstance(items.get(position))); + } - private List createItemsForSection(String section) { - int itemsNumber = 10; - List items = new ArrayList<>(itemsNumber); - for (int i = 0; i < itemsNumber; i++) { - items.add(section + " " + (i + 1)); + private List createItemsForSection(String section) { + int itemsNumber = 10; + List items = new ArrayList<>(itemsNumber); + for (int i = 0; i < itemsNumber; i++) { + items.add(section + " " + (i + 1)); + } + return items; } - return items; - } - @SuppressWarnings("ConstantConditions") - private void setUpActionBar() { - ActionBar actionBar = ((MainActivity) getActivity()).getSupportActionBar(); - actionBar.setDisplayHomeAsUpEnabled(false); - actionBar.setTitle(R.string.app_name); - } + @SuppressWarnings("ConstantConditions") + private void setUpActionBar() { + ActionBar actionBar = ((MainActivity) getActivity()).getSupportActionBar(); + actionBar.setDisplayHomeAsUpEnabled(false); + actionBar.setTitle(R.string.app_name); + } } \ No newline at end of file diff --git a/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/MainActivity.java b/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/MainActivity.java index 4f5d7f6..003d368 100644 --- a/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/MainActivity.java +++ b/multibackstack-sample/src/main/java/com/jetradar/multibackstack/sample/MainActivity.java @@ -17,146 +17,146 @@ package com.jetradar.multibackstack.sample; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; -import android.support.v4.util.Pair; import com.ashokvarma.bottomnavigation.BottomNavigationBar; import com.ashokvarma.bottomnavigation.BottomNavigationItem; import com.jetradar.multibackstack.BackStackActivity; -import static com.ashokvarma.bottomnavigation.BottomNavigationBar.OnTabSelectedListener; +import androidx.annotation.NonNull; +import androidx.core.util.Pair; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +public class MainActivity extends BackStackActivity implements BottomNavigationBar.OnTabSelectedListener { + private static final String STATE_CURRENT_TAB_ID = "current_tab_id"; + private static final int MAIN_TAB_ID = 0; + + private BottomNavigationBar bottomNavBar; + private Fragment curFragment; + private int curTabId; + + @Override + protected void onCreate(Bundle state) { + super.onCreate(state); + setContentView(R.layout.activity_main); + setUpBottomNavBar(); + + if (state == null) { + bottomNavBar.selectTab(MAIN_TAB_ID, false); + showFragment(rootTabFragment(MAIN_TAB_ID)); + } + } -public class MainActivity extends BackStackActivity implements OnTabSelectedListener { - private static final String STATE_CURRENT_TAB_ID = "current_tab_id"; - private static final int MAIN_TAB_ID = 0; + private void setUpBottomNavBar() { + bottomNavBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation); + bottomNavBar + .addItem(new BottomNavigationItem(R.drawable.ic_search_24dp, R.string.search)) + .addItem(new BottomNavigationItem(R.drawable.ic_favorite_24dp, R.string.favorites)) + .addItem(new BottomNavigationItem(R.drawable.ic_profile_24dp, R.string.profile)) + .initialise(); + bottomNavBar.setTabSelectedListener(this); + } - private BottomNavigationBar bottomNavBar; - private Fragment curFragment; - private int curTabId; + @NonNull + private Fragment rootTabFragment(int tabId) { + switch (tabId) { + case 0: + return ItemListFragment.newInstance(getString(R.string.search)); + case 1: + return ItemListFragment.newInstance(getString(R.string.favorites)); + case 2: + return ItemListFragment.newInstance(getString(R.string.profile)); + default: + throw new IllegalArgumentException(); + } + } - @Override - protected void onCreate(Bundle state) { - super.onCreate(state); - setContentView(R.layout.activity_main); - setUpBottomNavBar(); + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + curFragment = getSupportFragmentManager().findFragmentById(R.id.content); + curTabId = savedInstanceState.getInt(STATE_CURRENT_TAB_ID); + bottomNavBar.selectTab(curTabId, false); + } - if (state == null) { - bottomNavBar.selectTab(MAIN_TAB_ID, false); - showFragment(rootTabFragment(MAIN_TAB_ID)); + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putInt(STATE_CURRENT_TAB_ID, curTabId); + super.onSaveInstanceState(outState); } - } - - private void setUpBottomNavBar() { - bottomNavBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation); - bottomNavBar - .addItem(new BottomNavigationItem(R.drawable.ic_search_24dp, R.string.search)) - .addItem(new BottomNavigationItem(R.drawable.ic_favorite_24dp, R.string.favorites)) - .addItem(new BottomNavigationItem(R.drawable.ic_profile_24dp, R.string.profile)) - .initialise(); - bottomNavBar.setTabSelectedListener(this); - } - - @NonNull - private Fragment rootTabFragment(int tabId) { - switch (tabId) { - case 0: - return ItemListFragment.newInstance(getString(R.string.search)); - case 1: - return ItemListFragment.newInstance(getString(R.string.favorites)); - case 2: - return ItemListFragment.newInstance(getString(R.string.profile)); - default: - throw new IllegalArgumentException(); + + @Override + public void onBackPressed() { + Pair pair = popFragmentFromBackStack(); + if (pair != null) { + backTo(pair.first, pair.second); + } else { + super.onBackPressed(); + } } - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - curFragment = getSupportFragmentManager().findFragmentById(R.id.content); - curTabId = savedInstanceState.getInt(STATE_CURRENT_TAB_ID); - bottomNavBar.selectTab(curTabId, false); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - outState.putInt(STATE_CURRENT_TAB_ID, curTabId); - super.onSaveInstanceState(outState); - } - - @Override - public void onBackPressed() { - Pair pair = popFragmentFromBackStack(); - if (pair != null) { - backTo(pair.first, pair.second); - } else { - super.onBackPressed(); + + @Override + public void onTabSelected(int position) { + if (curFragment != null) { + pushFragmentToBackStack(curTabId, curFragment); + } + curTabId = position; + Fragment fragment = popFragmentFromBackStack(curTabId); + if (fragment == null) { + fragment = rootTabFragment(curTabId); + } + replaceFragment(fragment); } - } - @Override - public void onTabSelected(int position) { - if (curFragment != null) { - pushFragmentToBackStack(curTabId, curFragment); + @Override + public void onTabReselected(int position) { + backToRoot(); } - curTabId = position; - Fragment fragment = popFragmentFromBackStack(curTabId); - if (fragment == null) { - fragment = rootTabFragment(curTabId); + + @Override + public void onTabUnselected(int position) { } - replaceFragment(fragment); - } - @Override - public void onTabReselected(int position) { - backToRoot(); - } + public void showFragment(@NonNull Fragment fragment) { + showFragment(fragment, true); + } - @Override - public void onTabUnselected(int position) {} + public void showFragment(@NonNull Fragment fragment, boolean addToBackStack) { + if (curFragment != null && addToBackStack) { + pushFragmentToBackStack(curTabId, curFragment); + } + replaceFragment(fragment); + } - public void showFragment(@NonNull Fragment fragment) { - showFragment(fragment, true); - } + private void backTo(int tabId, @NonNull Fragment fragment) { + if (tabId != curTabId) { + curTabId = tabId; + bottomNavBar.selectTab(curTabId, false); + } + replaceFragment(fragment); + getSupportFragmentManager().executePendingTransactions(); + } - public void showFragment(@NonNull Fragment fragment, boolean addToBackStack) { - if (curFragment != null && addToBackStack) { - pushFragmentToBackStack(curTabId, curFragment); + private void backToRoot() { + if (isRootTabFragment(curFragment, curTabId)) { + return; + } + resetBackStackToRoot(curTabId); + Fragment rootFragment = popFragmentFromBackStack(curTabId); + assert rootFragment != null; + backTo(curTabId, rootFragment); } - replaceFragment(fragment); - } - private void backTo(int tabId, @NonNull Fragment fragment) { - if (tabId != curTabId) { - curTabId = tabId; - bottomNavBar.selectTab(curTabId, false); + private boolean isRootTabFragment(@NonNull Fragment fragment, int tabId) { + return fragment.getClass() == rootTabFragment(tabId).getClass(); } - replaceFragment(fragment); - getSupportFragmentManager().executePendingTransactions(); - } - private void backToRoot() { - if (isRootTabFragment(curFragment, curTabId)) { - return; + private void replaceFragment(@NonNull Fragment fragment) { + FragmentManager fm = getSupportFragmentManager(); + FragmentTransaction tr = fm.beginTransaction(); + tr.replace(R.id.content, fragment); + tr.commitAllowingStateLoss(); + curFragment = fragment; } - resetBackStackToRoot(curTabId); - Fragment rootFragment = popFragmentFromBackStack(curTabId); - assert rootFragment != null; - backTo(curTabId, rootFragment); - } - - private boolean isRootTabFragment(@NonNull Fragment fragment, int tabId) { - return fragment.getClass() == rootTabFragment(tabId).getClass(); - } - - private void replaceFragment(@NonNull Fragment fragment) { - FragmentManager fm = getSupportFragmentManager(); - FragmentTransaction tr = fm.beginTransaction(); - tr.replace(R.id.content, fragment); - tr.commitAllowingStateLoss(); - curFragment = fragment; - } } \ No newline at end of file diff --git a/multibackstack-sample/src/main/res/values/styles.xml b/multibackstack-sample/src/main/res/values/styles.xml index e0b0d72..f9811d6 100644 --- a/multibackstack-sample/src/main/res/values/styles.xml +++ b/multibackstack-sample/src/main/res/values/styles.xml @@ -4,11 +4,6 @@ @color/colorPrimary @color/colorPrimaryDark @color/colorAccent - @style/Theme.MultiBackStack.ActionBar - - - \ No newline at end of file diff --git a/multibackstack/build.gradle b/multibackstack/build.gradle index e25b455..4e8e966 100644 --- a/multibackstack/build.gradle +++ b/multibackstack/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' dependencies { - compile rootProject.ext.supportAppCompat + implementation rootProject.ext.supportAppCompat } android { diff --git a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStack.java b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStack.java index 55c8b7e..0e57f28 100644 --- a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStack.java +++ b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStack.java @@ -18,68 +18,70 @@ import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; + import java.util.Stack; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + public class BackStack implements Parcelable { - public final int hostId; - private final Stack entriesStack = new Stack<>(); - - public BackStack(int hostId) { - this.hostId = hostId; - } - - public void push(@NonNull BackStackEntry entry) { - entriesStack.push(entry); - } - - @Nullable - public BackStackEntry pop() { - return empty() ? null : entriesStack.pop(); - } - - public boolean empty() { - return entriesStack.empty(); - } - - public int size() { - return entriesStack.size(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeInt(hostId); - int size = entriesStack.size(); - out.writeInt(size); - for (int i = 0; i < size; i++) { - entriesStack.get(i).writeToParcel(out, flags); + public final int hostId; + private final Stack entriesStack = new Stack<>(); + + public BackStack(int hostId) { + this.hostId = hostId; } - } - private BackStack(Parcel in) { - hostId = in.readInt(); - int size = in.readInt(); - for (int i = 0; i < size; i++) { - entriesStack.push(BackStackEntry.CREATOR.createFromParcel(in)); + public void push(@NonNull BackStackEntry entry) { + entriesStack.push(entry); } - } - public static final Creator CREATOR = new Creator() { + @Nullable + public BackStackEntry pop() { + return empty() ? null : entriesStack.pop(); + } + + public boolean empty() { + return entriesStack.empty(); + } + + public int size() { + return entriesStack.size(); + } @Override - public BackStack createFromParcel(Parcel in) { - return new BackStack(in); + public int describeContents() { + return 0; } @Override - public BackStack[] newArray(int size) { - return new BackStack[size]; + public void writeToParcel(Parcel out, int flags) { + out.writeInt(hostId); + int size = entriesStack.size(); + out.writeInt(size); + for (int i = 0; i < size; i++) { + entriesStack.get(i).writeToParcel(out, flags); + } + } + + private BackStack(Parcel in) { + hostId = in.readInt(); + int size = in.readInt(); + for (int i = 0; i < size; i++) { + entriesStack.push(BackStackEntry.CREATOR.createFromParcel(in)); + } } - }; + + public static final Creator CREATOR = new Creator() { + + @Override + public BackStack createFromParcel(Parcel in) { + return new BackStack(in); + } + + @Override + public BackStack[] newArray(int size) { + return new BackStack[size]; + } + }; } \ No newline at end of file diff --git a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackActivity.java b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackActivity.java index e422ef4..52dd487 100644 --- a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackActivity.java +++ b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackActivity.java @@ -17,88 +17,89 @@ package com.jetradar.multibackstack; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.util.Pair; -import android.support.v7.app.AppCompatActivity; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.util.Pair; +import androidx.fragment.app.Fragment; + public abstract class BackStackActivity extends AppCompatActivity { - private static final String STATE_BACK_STACK_MANAGER = "back_stack_manager"; + private static final String STATE_BACK_STACK_MANAGER = "back_stack_manager"; - protected BackStackManager backStackManager; + protected BackStackManager backStackManager; - @Override - protected void onCreate(Bundle state) { - super.onCreate(state); - backStackManager = new BackStackManager(); - } + @Override + protected void onCreate(Bundle state) { + super.onCreate(state); + backStackManager = new BackStackManager(); + } - @Override - protected void onDestroy() { - backStackManager = null; - super.onDestroy(); - } + @Override + protected void onDestroy() { + backStackManager = null; + super.onDestroy(); + } - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putParcelable(STATE_BACK_STACK_MANAGER, backStackManager.saveState()); - } + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(STATE_BACK_STACK_MANAGER, backStackManager.saveState()); + } - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - backStackManager.restoreState(savedInstanceState.getParcelable(STATE_BACK_STACK_MANAGER)); - } + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + backStackManager.restoreState(savedInstanceState.getParcelable(STATE_BACK_STACK_MANAGER)); + } - /** - * @return false if failed to put fragment in back stack. Relates to issue: - * java.lang.IllegalStateException: Fragment is not currently in the FragmentManager at - * android.support.v4.app.FragmentManagerImpl.saveFragmentInstanceState(FragmentManager.java:702) - */ - protected boolean pushFragmentToBackStack(int hostId, @NonNull Fragment fragment) { - try { - BackStackEntry entry = BackStackEntry.create(getSupportFragmentManager(), fragment); - backStackManager.push(hostId, entry); - return true; - } catch (Exception e) { - Log.e("MultiBackStack", "Failed to add fragment to back stack", e); - return false; + /** + * @return false if failed to put fragment in back stack. Relates to issue: + * java.lang.IllegalStateException: Fragment is not currently in the FragmentManager at + * android.support.v4.app.FragmentManagerImpl.saveFragmentInstanceState(FragmentManager.java:702) + */ + protected boolean pushFragmentToBackStack(int hostId, @NonNull Fragment fragment) { + try { + BackStackEntry entry = BackStackEntry.create(getSupportFragmentManager(), fragment); + backStackManager.push(hostId, entry); + return true; + } catch (Exception e) { + Log.e("MultiBackStack", "Failed to add fragment to back stack", e); + return false; + } } - } - @Nullable - protected Fragment popFragmentFromBackStack(int hostId) { - BackStackEntry entry = backStackManager.pop(hostId); - return entry != null ? entry.toFragment(this) : null; - } + @Nullable + protected Fragment popFragmentFromBackStack(int hostId) { + BackStackEntry entry = backStackManager.pop(hostId); + return entry != null ? entry.toFragment(this) : null; + } - @Nullable - protected Pair popFragmentFromBackStack() { - Pair pair = backStackManager.pop(); - return pair != null ? Pair.create(pair.first, pair.second.toFragment(this)) : null; - } + @Nullable + protected Pair popFragmentFromBackStack() { + Pair pair = backStackManager.pop(); + return pair != null ? Pair.create(pair.first, pair.second.toFragment(this)) : null; + } - /** - * @return false if back stack is missing. - */ - protected boolean resetBackStackToRoot(int hostId) { - return backStackManager.resetToRoot(hostId); - } + /** + * @return false if back stack is missing. + */ + protected boolean resetBackStackToRoot(int hostId) { + return backStackManager.resetToRoot(hostId); + } - /** - * @return false if back stack is missing. - */ - protected boolean clearBackStack(int hostId) { - return backStackManager.clear(hostId); - } + /** + * @return false if back stack is missing. + */ + protected boolean clearBackStack(int hostId) { + return backStackManager.clear(hostId); + } - /** - * @return the number of fragments in back stack. - */ - protected int backStackSize(int hostId) { - return backStackManager.backStackSize(hostId); - } + /** + * @return the number of fragments in back stack. + */ + protected int backStackSize(int hostId) { + return backStackManager.backStackSize(hostId); + } } \ No newline at end of file diff --git a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackEntry.java b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackEntry.java index 2ca393d..11497ed 100644 --- a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackEntry.java +++ b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackEntry.java @@ -20,94 +20,95 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.Fragment.SavedState; -import android.support.v4.app.FragmentManager; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.Fragment.SavedState; +import androidx.fragment.app.FragmentManager; public class BackStackEntry implements Parcelable { - public final String fname; - public final SavedState state; - public final Bundle args; - - public BackStackEntry(@NonNull String fname, @Nullable SavedState state, @Nullable Bundle args) { - this.fname = fname; - this.state = state; - this.args = args; - } - - @NonNull - public static BackStackEntry create(@NonNull FragmentManager fm, @NonNull Fragment f) { - String fname = f.getClass().getName(); - SavedState state = fm.saveFragmentInstanceState(f); - Bundle args = f.getArguments(); - return new BackStackEntry(fname, state, args); - } - - @NonNull - public Fragment toFragment(@NonNull Context context) { - Fragment f = Fragment.instantiate(context, fname); - f.setInitialSavedState(state); - f.setArguments(args); - return f; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeString(fname); - out.writeBundle(args); - - if (state == null) { - out.writeInt(NO_STATE); - } else if (state.getClass() == SavedState.class) { - out.writeInt(SAVED_STATE); - state.writeToParcel(out, flags); - } else { - out.writeInt(PARCELABLE_STATE); - out.writeParcelable(state, flags); - } - } - - private BackStackEntry(Parcel in) { - final ClassLoader loader = getClass().getClassLoader(); - fname = in.readString(); - args = in.readBundle(loader); - - switch (in.readInt()) { - case NO_STATE: - state = null; - break; - case SAVED_STATE: - state = SavedState.CREATOR.createFromParcel(in); - break; - case PARCELABLE_STATE: - state = in.readParcelable(loader); - break; - default: - throw new IllegalStateException(); + public final String fname; + public final SavedState state; + public final Bundle args; + + public BackStackEntry(@NonNull String fname, @Nullable SavedState state, @Nullable Bundle args) { + this.fname = fname; + this.state = state; + this.args = args; } - } - private static final int NO_STATE = -1; - private static final int SAVED_STATE = 0; - private static final int PARCELABLE_STATE = 1; + @NonNull + public static BackStackEntry create(@NonNull FragmentManager fm, @NonNull Fragment f) { + String fname = f.getClass().getName(); + SavedState state = fm.saveFragmentInstanceState(f); + Bundle args = f.getArguments(); + return new BackStackEntry(fname, state, args); + } - public static final Creator CREATOR = new Creator() { + @NonNull + public Fragment toFragment(@NonNull Context context) { + Fragment f = Fragment.instantiate(context, fname); + f.setInitialSavedState(state); + f.setArguments(args); + return f; + } @Override - public BackStackEntry createFromParcel(Parcel in) { - return new BackStackEntry(in); + public int describeContents() { + return 0; } @Override - public BackStackEntry[] newArray(int size) { - return new BackStackEntry[size]; + public void writeToParcel(Parcel out, int flags) { + out.writeString(fname); + out.writeBundle(args); + + if (state == null) { + out.writeInt(NO_STATE); + } else if (state.getClass() == SavedState.class) { + out.writeInt(SAVED_STATE); + state.writeToParcel(out, flags); + } else { + out.writeInt(PARCELABLE_STATE); + out.writeParcelable(state, flags); + } } - }; + + private BackStackEntry(Parcel in) { + final ClassLoader loader = getClass().getClassLoader(); + fname = in.readString(); + args = in.readBundle(loader); + + switch (in.readInt()) { + case NO_STATE: + state = null; + break; + case SAVED_STATE: + state = SavedState.CREATOR.createFromParcel(in); + break; + case PARCELABLE_STATE: + state = in.readParcelable(loader); + break; + default: + throw new IllegalStateException(); + } + } + + private static final int NO_STATE = -1; + private static final int SAVED_STATE = 0; + private static final int PARCELABLE_STATE = 1; + + public static final Creator CREATOR = new Creator() { + + @Override + public BackStackEntry createFromParcel(Parcel in) { + return new BackStackEntry(in); + } + + @Override + public BackStackEntry[] newArray(int size) { + return new BackStackEntry[size]; + } + }; } \ No newline at end of file diff --git a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackManager.java b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackManager.java index 1a5cbdc..f9d7f9d 100644 --- a/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackManager.java +++ b/multibackstack/src/main/java/com/jetradar/multibackstack/BackStackManager.java @@ -18,181 +18,182 @@ import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.util.Pair; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -public class BackStackManager { - private static final int FIRST_INDEX = 0; - private static final int UNDEFINED_INDEX = -1; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.util.Pair; - protected final LinkedList backStacks = new LinkedList<>(); +public class BackStackManager { + private static final int FIRST_INDEX = 0; + private static final int UNDEFINED_INDEX = -1; - public void push(int hostId, @NonNull BackStackEntry entry) { - BackStack backStack = peekBackStack(hostId); - if (backStack == null) { - backStack = new BackStack(hostId); - backStacks.push(backStack); - } - backStack.push(entry); - } - - @Nullable - public BackStackEntry pop(int hostId) { - BackStack backStack = peekBackStack(hostId); - if (backStack == null) { - return null; - } - return pop(backStack); - } - - @Nullable - public Pair pop() { - BackStack backStack = peekBackStack(); - if (backStack == null) { - return null; - } - return Pair.create(backStack.hostId, pop(backStack)); - } - - @NonNull - protected BackStackEntry pop(@NonNull BackStack backStack) { - BackStackEntry entry = backStack.pop(); - assert entry != null; - if (backStack.empty()) { - backStacks.remove(backStack); - } - return entry; - } + protected final LinkedList backStacks = new LinkedList<>(); - public boolean clear(int hostId) { - BackStack backStack = getBackStack(hostId); - if (backStack == null) { - return false; - } - backStacks.remove(backStack); - return true; - } - - public int backStackSize(int hostId) { - BackStack backStack = getBackStack(hostId); - return backStack!= null ? backStack.size() : 0; - } - - public boolean resetToRoot(int hostId) { - BackStack backStack = getBackStack(hostId); - if (backStack == null) { - return false; - } - resetToRoot(backStack); - return true; - } - - protected void resetToRoot(@NonNull BackStack backStack) { - while (true) { - BackStackEntry entry = backStack.pop(); - assert entry != null; - if (backStack.empty()) { + public void push(int hostId, @NonNull BackStackEntry entry) { + BackStack backStack = peekBackStack(hostId); + if (backStack == null) { + backStack = new BackStack(hostId); + backStacks.push(backStack); + } backStack.push(entry); - return; - } } - } - @Nullable - protected BackStack peekBackStack(int hostId) { - int index = indexOfBackStack(hostId); - if (index == UNDEFINED_INDEX) { - return null; - } - BackStack backStack = backStacks.get(index); - if (index != FIRST_INDEX) { - backStacks.remove(index); - backStacks.push(backStack); + @Nullable + public BackStackEntry pop(int hostId) { + BackStack backStack = peekBackStack(hostId); + if (backStack == null) { + return null; + } + return pop(backStack); + } + + @Nullable + public Pair pop() { + BackStack backStack = peekBackStack(); + if (backStack == null) { + return null; + } + return Pair.create(backStack.hostId, pop(backStack)); } - return backStack; - } - - @Nullable - protected BackStack peekBackStack() { - return backStacks.peek(); - } - - @Nullable - protected BackStack getBackStack(int hostId) { - int index = indexOfBackStack(hostId); - if (index == UNDEFINED_INDEX) { - return null; + + @NonNull + protected BackStackEntry pop(@NonNull BackStack backStack) { + BackStackEntry entry = backStack.pop(); + assert entry != null; + if (backStack.empty()) { + backStacks.remove(backStack); + } + return entry; + } + + public boolean clear(int hostId) { + BackStack backStack = getBackStack(hostId); + if (backStack == null) { + return false; + } + backStacks.remove(backStack); + return true; + } + + public int backStackSize(int hostId) { + BackStack backStack = getBackStack(hostId); + return backStack != null ? backStack.size() : 0; + } + + public boolean resetToRoot(int hostId) { + BackStack backStack = getBackStack(hostId); + if (backStack == null) { + return false; + } + resetToRoot(backStack); + return true; + } + + protected void resetToRoot(@NonNull BackStack backStack) { + while (true) { + BackStackEntry entry = backStack.pop(); + assert entry != null; + if (backStack.empty()) { + backStack.push(entry); + return; + } + } + } + + @Nullable + protected BackStack peekBackStack(int hostId) { + int index = indexOfBackStack(hostId); + if (index == UNDEFINED_INDEX) { + return null; + } + BackStack backStack = backStacks.get(index); + if (index != FIRST_INDEX) { + backStacks.remove(index); + backStacks.push(backStack); + } + return backStack; + } + + @Nullable + protected BackStack peekBackStack() { + return backStacks.peek(); + } + + @Nullable + protected BackStack getBackStack(int hostId) { + int index = indexOfBackStack(hostId); + if (index == UNDEFINED_INDEX) { + return null; + } + return backStacks.get(index); + } + + protected int indexOfBackStack(int hostId) { + int size = backStacks.size(); + for (int i = 0; i < size; i++) { + if (backStacks.get(i).hostId == hostId) { + return i; + } + } + return UNDEFINED_INDEX; + } + + @NonNull + public Parcelable saveState() { + return new SavedState(backStacks); + } + + public void restoreState(@Nullable Parcelable state) { + if (state != null) { + SavedState savedState = (SavedState) state; + backStacks.addAll(savedState.backStacks); + } + } + + static class SavedState implements Parcelable { + final List backStacks; + + public SavedState(List backStacks) { + this.backStacks = backStacks; + } + + private SavedState(Parcel in) { + int size = in.readInt(); + backStacks = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + backStacks.add(BackStack.CREATOR.createFromParcel(in)); + } + } + + @Override + public void writeToParcel(Parcel out, int flags) { + int size = backStacks.size(); + out.writeInt(size); + for (int i = 0; i < size; i++) { + backStacks.get(i).writeToParcel(out, flags); + } + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; } - return backStacks.get(index); - } - - protected int indexOfBackStack(int hostId) { - int size = backStacks.size(); - for (int i = 0; i < size; i++) { - if (backStacks.get(i).hostId == hostId) { - return i; - } - } - return UNDEFINED_INDEX; - } - - @NonNull - public Parcelable saveState() { - return new SavedState(backStacks); - } - - public void restoreState(@Nullable Parcelable state) { - if (state != null) { - SavedState savedState = (SavedState) state; - backStacks.addAll(savedState.backStacks); - } - } - - static class SavedState implements Parcelable { - final List backStacks; - - public SavedState(List backStacks) { - this.backStacks = backStacks; - } - - private SavedState(Parcel in) { - int size = in.readInt(); - backStacks = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - backStacks.add(BackStack.CREATOR.createFromParcel(in)); - } - } - - @Override - public void writeToParcel(Parcel out, int flags) { - int size = backStacks.size(); - out.writeInt(size); - for (int i = 0; i < size; i++) { - backStacks.get(i).writeToParcel(out, flags); - } - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator CREATOR = new Creator() { - - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } } \ No newline at end of file