ViewPager cause crash - android

I have a viewpager. The viewpager has five fragments. And these fragments have child fragments. When I start my app, it crashes. If I comment out resetMenu() function it works. What is the problem?
HomeActivity.java
#Override
public void onPageSelected(int position) {
listeners[beforePagerPosition].onViewPaused();
tabLayout.getTabAt(beforePagerPosition).getIcon().setAlpha(getResources().getInteger(R.integer.tab_unselected_alpha));
beforePagerPosition = position;
tabLayout.getTabAt(position).getIcon().setAlpha(getResources().getInteger(R.integer.tab_selected_alpha));
listeners[position].onViewResumed();
resetMenu();
hideKeyboard();
}
#Override
public void onPageScrollStateChanged(int state) {
}
private void resetMenu() {
if (getSupportFragmentManager() != null) {
ParentFragment parentFragment = (ParentFragment) listeners[viewPager.getCurrentItem()];
FragmentManager fm = parentFragment.getChildFragmentManager();
if (fm != null && fm.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry backStackEntry = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1);
String str = backStackEntry.getName();
BaseMenuFragment fragment = (BaseMenuFragment) fm.findFragmentByTag(str);
fragment.setHasOptionsMenu(true);
}
}
}

OK. I found answer. I added control for ParentFragment isAdded().
ParentFragment parentFragment = (ParentFragment) listeners[viewPager.getCurrentItem()];
if(parentFragment.isAdded()){
....
}

Related

Save state of fragment when using bottom navigation

I am using bottom navigation drawer to switch between fragments, the problem is that every time I switch back to a fragment it gets recreated.
How can I save the state of fragment and resume it when switched back to it?
bottomNavigationBar.setTabSelectedListener(new BottomNavigationBar.OnTabSelectedListener(){
#Override
public void onTabSelected(int position) {
if (position==0){
loadFragment(new Daily());
}
if (position==1){
loadFragment(new Trending());
}
if (position==2){
loadFragment(new Random());
}
}
#Override
public void onTabUnselected(int position) {
}
#Override
public void onTabReselected(int position) {
}
});
private void loadFragment(Fragment fragment) {
// load fragment
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.attach( fragment);
transaction.addToBackStack(null);
transaction.commit();
}
The issue is that you are always creating a new Fragment on any onTabSelected. So in order to fix it, you need to work with your FragmentManager.
Possible solution: use the add and show/hide methods.
Example:
private static final String DAILY_TAG = BuildConfig.APPLICATION_ID + ".DAILY_TAG";
private static final String TRENDING_TAG = BuildConfig.APPLICATION_ID + ".TRENDING_TAG";
private static final String RANDOM_TAG = BuildConfig.APPLICATION_ID + ".RANDOM_TAG";
public void onTabSelected(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
if (position == 0) {
hideFragment(TRENDING_TAG)
hideFragment(RANDOM_TAG)
Fragment fragment = fragmentManager.findFragmentByTag(DAILY_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction()
if (fragment != null) {
transaction.show(fragment)
} else {
transaction.add(content.id, new Daily(), DAILY_TAG)
}
transaction.commitNow()
} else if (position == 1) {
hideFragment(DAILY_TAG)
hideFragment(RANDOM_TAG)
Fragment fragment = fragmentManager.findFragmentByTag(TRENDING_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction()
if (fragment != null) {
transaction.show(fragment)
} else {
transaction.add(content.id, new Trending(), TRENDING_TAG)
}
transaction.commitNow()
} else {
hideFragment(TRENDING_TAG)
hideFragment(DAILY_TAG)
Fragment fragment = fragmentManager.findFragmentByTag(RANDOM_TAG);
FragmentTransaction transaction = fragmentManager.beginTransaction()
if (fragment != null) {
transaction.show(fragment)
} else {
transaction.add(content.id, new Random(), RANDOM_TAG)
}
transaction.commitNow()
}
fragments.put(position, fragment);
loadFragment(fragment);
}
private void hideFragment(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager()
Fragment currentFragment = fragmentManager.findFragmentByTag(tag)
if (currentFragment != null) {
fragmentManager.beginTransaction().hide(currentFragment).commitNow()
}
}
PS - The code can be optimized.

App crashes when using getActionBar.setTitle(); while extending FragmentActivity

App crashes getting null pointer exception in getActionBar.setTitle(....)
? How to solve it ? I tried getSupportActionBar instead of getActionBar..
but it does not worked ? can someone help me ..
package com.msinfolab.mandy.tfq;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends FragmentActivity{
private Fragment contentFragment;
QuotecardListFragment pdtListFragment;
FavoriteListFragment favListFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
/*
* This is called when orientation is changed.
*/
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("content")) {
String content = savedInstanceState.getString("content");
if (content.equals(FavoriteListFragment.ARG_ITEM_ID)) {
if (fragmentManager.findFragmentByTag(FavoriteListFragment.ARG_ITEM_ID) != null) {
setFragmentTitle(R.string.favorites);
contentFragment = fragmentManager
.findFragmentByTag(FavoriteListFragment.ARG_ITEM_ID);
}
}
}
if (fragmentManager.findFragmentByTag(QuotecardListFragment.ARG_ITEM_ID) != null) {
pdtListFragment = (QuotecardListFragment) fragmentManager
.findFragmentByTag(QuotecardListFragment.ARG_ITEM_ID);
contentFragment = pdtListFragment;
}
} else {
pdtListFragment = new QuotecardListFragment();
setFragmentTitle(R.string.app_name);
switchContent(pdtListFragment, QuotecardListFragment.ARG_ITEM_ID);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
if (contentFragment instanceof FavoriteListFragment) {
outState.putString("content", FavoriteListFragment.ARG_ITEM_ID);
} else {
outState.putString("content", QuotecardListFragment.ARG_ITEM_ID);
}
super.onSaveInstanceState(outState);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_favorites:
setFragmentTitle(R.string.favorites);
favListFragment = new FavoriteListFragment();
switchContent(favListFragment, FavoriteListFragment.ARG_ITEM_ID);
return true;
}
return super.onOptionsItemSelected(item);
}
public void switchContent(Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
while (fragmentManager.popBackStackImmediate());
if (fragment != null) {
FragmentTransaction transaction = fragmentManager
.beginTransaction();
transaction.replace(R.id.content_frame, fragment, tag);
if (!(fragment instanceof QuotecardListFragment)) {
transaction.addToBackStack(tag);
}
transaction.commit();
contentFragment = fragment;
}
}
protected void setFragmentTitle(int resourseId) {
setTitle(resourseId);
getActionBar().setTitle(resourseId);
}
#Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
super.onBackPressed();
} else if (contentFragment instanceof QuotecardListFragment
|| fm.getBackStackEntryCount() == 0) {
finish();
}
}
}
this part of code warns a null pointer exception .. how to correct it ?
protected void setFragmentTitle(int resourseId) {
setTitle(resourseId);
getActionBar().setTitle(resourseId);
}
and another warning.. equals may produce null pointer exception.. how to solve this problem
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("content")) {
String content = savedInstanceState.getString("content");
if (content.equals(FavoriteListFragment.ARG_ITEM_ID)) {
if (fragmentManager.findFragmentByTag(FavoriteListFragment.ARG_ITEM_ID) != null) {
setFragmentTitle(R.string.favorites);
contentFragment = fragmentManager
.findFragmentByTag(FavoriteListFragment.ARG_ITEM_ID);
}
}
}
if (fragmentManager.findFragmentByTag(QuotecardListFragment.ARG_ITEM_ID) != null) {
pdtListFragment = (QuotecardListFragment) fragmentManager
.findFragmentByTag(QuotecardListFragment.ARG_ITEM_ID);
contentFragment = pdtListFragment;
}
} else {
pdtListFragment = new QuotecardListFragment();
setFragmentTitle(R.string.app_name);
switchContent(pdtListFragment, QuotecardListFragment.ARG_ITEM_ID);
}
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("Profile");
Hope its work
Create Toolbar layout which should be a common toolbar for all fragments.And set title for the toolbars like toolbar.setTitle(getString(R.string.menu_category));
First of all, you need to define your own toolbar in fragment layout XML, have you done?
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary">
</android.support.v7.widget.Toolbar>
Then in your onCreate method, before setting title you need to do this:
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
And finally in your setFragmentTitle method, you set the toolbar title like this:
((Toolbar) findViewById(R.id.toolbar)).setTitle(resourseId);
Please let me know if the problem is resolved.

IllegalStateException Fragment already added - Android

I am adding fragment like bellow :
#OnClick(R.id.lnNews)
void newsList() {
String tagName = returnStatusFragment(getString(R.string.news_list_fragment));
if (!TextUtils.isEmpty(tagName) && tagName.equals(getString(R.string.news_list_fragment))) {
frameWorkTableFragment.setVisibility(View.VISIBLE);
if (getActivity() != null) {
android.support.v4.app.FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
Fragment news = fragmentManager.findFragmentByTag(getString(R.string.news_list_fragment));
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_work_table_fragment,
news,
getString(R.string.news_list_fragment)).commit();
}
//Fragment is opened
} else {
if (getActivity() != null) {
frameWorkTableFragment.setVisibility(View.VISIBLE);
NewsListFragment newsListFragment = new NewsListFragment();
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_work_table_fragment,
newsListFragment,
getString(R.string.news_list_fragment))
.addToBackStack(getString(R.string.news_list_fragment))
.commit();
}
}
}
And in the Fragment I wrote doBackPress like bellow :
#Override
public void doBackTabZero(String nameFragment) {
android.support.v4.app.FragmentManager fragmentManagers = getActivity().getSupportFragmentManager();
if (fragmentManagers.getBackStackEntryCount() > 1) {
fragmentManagers.popBackStackImmediate();
} else {
if (nameFragment.equals("SignsFragment")) {
BusDisplayStatusFrameLayout busDisplayStatusFrameLayout = new BusDisplayStatusFrameLayout();
busDisplayStatusFrameLayout.setDisplayStatusFrameLayout(1);
EventBus.getDefault().post(busDisplayStatusFrameLayout);
android.support.v4.app.FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentManager.popBackStackImmediate();
fragmentTransaction.remove(SignsFragment.this);
fragmentTransaction.commit();
}
}
}
But get me crash often in this line :
fragmentManagers.popBackStackImmediate();
With this message :
java.lang.IllegalStateException: Fragment already added: NewsFragment{aed4cd1 #3 id=0x7f0a006e NewsFragment}
And in my activity my doBack is like bellow :
private Fragment getCurrentFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
String fragmentTag = fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount() - 1).getName();
return fragmentManager.findFragmentByTag(fragmentTag);
}
Then :
#Override
public void onBackPressed() {
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount > 0) {
if (onBackPressedListenerTabWorkTable != null || onBackPressedListenerTabMou != null) {
if (getCurrentFragment().getTag() != null && !TextUtils.isEmpty(getCurrentFragment().getTag())) {
if (getCurrentFragment().getTag().equals("EventsFragment")
|| getCurrentFragment().getTag().equals("WebViewListClassFragment")
|| getCurrentFragment().getTag().equals("SignsFragment")
|| getCurrentFragment().getTag().equals("NewsListFragment")) {
if (viewPagerMainActivity.getCurrentItem() != 0) {
viewPagerMainActivity.setCurrentItem(0);
}
onBackPressedListenerTabWorkTable.doBackTabZero(getCurrentFragment().getTag());
} else if (getCurrentFragment().getTag().equals("SpecialNewsMouFragment")) {
if (viewPagerMainActivity.getCurrentItem() != 1) {
viewPagerMainActivity.setCurrentItem(1);
}
onBackPressedListenerTabMou.doBackTabOne(getCurrentFragment().getTag());
}
}
}
} else {
super.onBackPressed();
onBackPressedListenerTabWorkTable = null;
onBackPressedListenerTabMou = null;
finish();
}
}

How to avoid fragment duplication issue?

I have the following code:
private List<WeakReference<Fragment>> mFragList = new ArrayList<WeakReference<Fragment>>();
#Override
public void onAttachFragment (Fragment fragment) {
mFragList.add(new WeakReference(fragment));
}
public List<Fragment> getActiveFragments() {
ArrayList<Fragment> ret = new ArrayList<Fragment>();
for(WeakReference<Fragment> ref : mFragList) {
Fragment f = ref.get();
if(f != null) {
if(f.isVisible()) {
ret.add(f);
}
}
}
return ret;
}
public Fragment findFragement(String tClass) {
List<Fragment> fragments = getActiveFragments();
for (Fragment fragment : fragments) {
if (tClass.equalsIgnoreCase("Home")) {
if (fragment instanceof ToggleFragment) {
return fragment;
}
} else if (tClass.equalsIgnoreCase("Contacts")) {
if (fragment instanceof ContactFragment) {
return fragment;
}
}
}
return null;
}
The code works fine, but I have a concern, wouldn't this code:
#Override
public void onAttachFragment (Fragment fragment) {
mFragList.add(new WeakReference(fragment));
}
cause duplicates when a screen is recreated or ft.replace() is used?
Is there a better way around this ? without replacing much code or without using getsupportfragmentmanager.getfragments() ?
Thanks!
One way to guarantee that there aren't duplicates is to use a map. You could add this line to the top of your class
private static final String TAG = "MyFragmentClassName";
Then, instead of using an ArrayList, you can use
Map<String, WeakReference<Fragment>> fragmentMap = new HashMap<>();
and add fragments to the map with
map.put(TAG, myWeakReferenceInstance);
When you want to add items, you can check if something is in that spot already by checking
if (map.get(TAG) != null) {
//do something
}
This should work for you, but I still have to recommend using getSupportFragmentManager(). You can do all of this and more with it. For example, this is some code I've been using in this music app I've been building:
private void showAlbumListFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
albumListFragment = new AlbumListFragment();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, albumListFragment, AlbumListFragment.TAG)
.commit();
}
If you wanted to avoid duplication, you could just add a few lines:
private void showAlbumListFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
albumListFragment = (AlbumListFragment) fragmentManager.findFragmentByTag(AlbumListFragment.TAG);
if (albumListFragment == null) {
albumListFragment = new AlbumListFragment();
}
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, albumListFragment, AlbumListFragment.TAG)
.commit();
}

On click Blank Area Next Fragment Automaticall call

I have 3 fragments open on condition of First fragments list item Click >> Second fragment open and so on Second. But when I click on first fragment's blank space it automatically open second fragment and click on second fragment's blank space it goes to third fragment
This is class I have maintain for fragment transaction
public static void addABCDHomeFragment(FragmentManager fragManager, String categoryName) {
FragmentTransaction ft = fragManager.beginTransaction();
Fragment abcdHomeFragment = fragManager.findFragmentByTag(ABCD_HOME_FRAGMENT);
if (abcdHomeFragment == null || abcdHomeFragment.isRemoving()) {
ABCDHomeFragment homeFragment = new ABCDHomeFragment(categoryName);
ft.add(R.id.frame_layout, homeFragment, ABCD_HOME_FRAGMENT);
ft.addToBackStack(ABCD_HOME_FRAGMENT);
ft.commit();
} else if (abcdHomeFragment != null && abcdHomeFragment.isAdded()) {
fragManager.popBackStack();
ABCDHomeFragment homeFragment = new ABCDHomeFragment(categoryName);
ft.replace(R.id.frame_layout, homeFragment, ABCD_HOME_FRAGMENT);
ft.addToBackStack(ABCD_HOME_FRAGMENT);
ft.commit();
}
}
public static void addProductListFragment(FragmentManager fragmentManager,String categoryId ,
String parent , int option) {
FragmentTransaction ftproductlist = fragmentManager.beginTransaction();
Fragment plistFragment = fragmentManager.findFragmentByTag(PRODUCT_LIST_FRAGMENT);
ProductListFragment productListFragment = new ProductListFragment(categoryId,parent,option);
if (plistFragment != null && plistFragment.isAdded() && plistFragment.isVisible()) {
fragmentManager.popBackStack();
ftproductlist.add(R.id.frame_layout, productListFragment,PRODUCT_LIST_FRAGMENT);
ftproductlist.addToBackStack(PRODUCT_LIST_FRAGMENT);
ftproductlist.commit();
} else {
ftproductlist.replace(R.id.frame_layout, productListFragment, PRODUCT_LIST_FRAGMENT);
ftproductlist.addToBackStack(PRODUCT_LIST_FRAGMENT);
ftproductlist.commit();
}
}
public static void removeProductListFragment(FragmentManager fragmentManager) {
FragmentTransaction ftproductlist = fragmentManager.beginTransaction();
Fragment productListFragment = fragmentManager.findFragmentByTag(PRODUCT_LIST_FRAGMENT);
if (productListFragment != null && productListFragment.isAdded()) {
ftproductlist.remove(productListFragment);
fragmentManager.popBackStack();
ftproductlist.commit();
}
}
public static void addProductDetailFragment(FragmentManager fragManager,String productId,String parent, String productName) {
FragmentTransaction ftproduct = fragManager.beginTransaction();
Fragment productDetailFragment = fragManager.findFragmentByTag(PRODUCT_DETAIL_FRAGMENT);
if (productDetailFragment == null || productDetailFragment.isRemoving()) {
ProductDetailFragment dtailFragment = new ProductDetailFragment(productId, parent,productName);
ftproduct.add(R.id.frame_layout, dtailFragment, PRODUCT_DETAIL_FRAGMENT);
ftproduct.addToBackStack(PRODUCT_DETAIL_FRAGMENT);
ftproduct.commit();
} else if (productDetailFragment != null && productDetailFragment.isAdded()) {
fragManager.popBackStack();
ProductDetailFragment dtailFragment = new ProductDetailFragment(productId,parent,productName);
ftproduct.replace(R.id.frame_layout, dtailFragment,PRODUCT_DETAIL_FRAGMENT);
ftproduct.addToBackStack(PRODUCT_DETAIL_FRAGMENT);
ftproduct.commit();
}
}

Categories

Resources