FragmentManager Error after updating from sdk 22 to 23 on Android - java

I'm using a FragmentPagerAdapter to create a 3 page viewpager and up until I upgraded to sdk 23 it worked fine. I am using one fragment and sending in different args depending on the getItem(position) to populate different data. After the upgrade Android isn't acknowledging one of the pages and I have to got to position 2 (page 3) and then slide back to position 0 (page 1) and then Android populates the page with the correct data. Running thru the debugger confirmed that Android skips over case 2 in the getItem function in TabAdapter.java. I am also getting
W/FragmentManager: moveToState: Fragment state for TabContentFragment{3ac2d125 #3 id=0x7f0f0097} not updated inline; expected state 3 found 2. I've been using this similar question as reference but still couldn't get it to work but I have cornered the problem down to the FragmentManager I am using. But after messing with it for hours I haven't been able to get Android to see that there are 3 pages not 2.
TabAdapter.java
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import com.movies.R;
import com.movies.date.LiveStatus;
import com.movies.fragments.TabContentFragment;
import com.movies.fragments.TabFragment;
import com.movies.utils.BundleKeys;
public class TabAdapter extends FragmentPagerAdapter {
private Context context;
public TabAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position) {
TabContentFragment fragment = new TabContentFragment();
Bundle args = new Bundle();
switch (position){
case 0:
args.putInt(BundleKeys.STATE_KEY, LiveStatus.EVENT_STARTED);
break;
case 1:
args.putInt(BundleKeys.STATE_KEY, LiveStatus.EVENT_NOT_STARTED);
break;
case 2:
args.putInt(BundleKeys.STATE_KEY, LiveStatus.EVENT_OVER);
break;
}
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return TabFragment.MAX_TABS;
}
/**
* This method returns the title of the tab according to the position.
*/
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return this.context.getString(R.string.tab_title_live);
case 1:
return this.context.getString(R.string.tab_title_upcoming);
case 2:
return this.context.getString(R.string.tab_title_replay);
default:
return null;
}
}
}
Data from bundle is pulled like this
this.state = getArguments().getInt(BundleKeys.STATE_KEY);
TabFragment.java
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.movies.R;
import com.movies.adapters.TabAdapter;
public class TabFragment extends Fragment {
public static final int MAX_TABS = 3;
public static TabLayout tabLayout;
public static ViewPager viewPager;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
* Inflate tab_layout and setup Views.
*/
View view = inflater.inflate(R.layout.tab_layout, null);
tabLayout = (TabLayout) view.findViewById(R.id.tabs);
viewPager = (ViewPager) view.findViewById(R.id.event_info_viewpager);
/**
* Set an Adapter for the View Pager
*/
viewPager.setAdapter(new TabAdapter(getFragmentManager(), getContext()));
/**
* Now , this is a workaround ,
* The setupWithViewPager doesn't works without the runnable .
* Maybe a Support Library Bug .
*/
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return view;
}
}
Activity that Holds the TabFragment starts fragment like this:
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.container_view, new TabFragment()).commit();

I'm not sure if I am understanding your question correctly or not but it sounds to me like your last (third) tab isn't being created until you navigate to it.
By default, the ViewPager is limited to creating only 2 off screen views (one to the left and one to the right). Typically, apps start off in the left most tab, meaning, if you have 3 in total, the right most tab will not be created until you navigate closer to it.
You can override this in your MainActivity by using ViewPager.setOffScreenPageLimit(#) where ViewPager is actually the name of your ViewPager and # is the number of tabs you want to create from the start. In your case it sounds like you want this number to be 2.

Related

Swipe tabs lagging when switching fragments

i have a little problem, i just have 3 fragments and i added to one of them a photoshop background (1080 x 1920) the thing is that when it loads to the phone the switching between the tabs lags a lot , but if i just render the image to 720 x 1280 it works fine and no lag appear, i implemented mViewPager.setOffscreenPageLimit(0); but it seems it dosnt work , i dont know what is causing the problem, i will let here my main code, thanks in advanced
import android.support.design.widget.TabLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
//-----------------------FRAGMENTS-----------------------
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
switch (position) {
case 0:
Fragment fragment = new DummySectionFragment3();
Bundle args = new Bundle();
args.putInt(DummySectionFragment3.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
case 1:
Fragment fragment2 = new DummySectionFragment2();
Bundle args2 = new Bundle();
args2.putInt(DummySectionFragment2.ARG_SECTION_NUMBER, position + 2);
fragment2.setArguments(args2);
return fragment2;
case 2:
Fragment fragment3 = new DummySectionFragment();
Bundle args3 = new Bundle();
args3.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 3);
fragment3.setArguments(args3);
return fragment3;
default:
return null;
}
}
//-----------------------FRAGMENTS-----------------------
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Bares";
case 1:
return "No se";
case 2:
return "Eventos";
}
return null;
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
}
i implemented mViewPager.setOffscreenPageLimit(0); but it seems it
dosnt work
Firstly,
Why did you set page limit to 0 if you are hoping for a smoother swipe ?
Do it as (if you have 3 tabs just set limiit to 1 , if 5 tabs, setting it to 2 would work)
mViewPager.setOffscreenPageLimit(2);
this means you are forcing caching of your 2 left and 2 right tabs from current tab.
So that they wont be loaded again and again instead they would be cached.
NOTE Having said that, you should keep in mind that it would consume more memory and avoid unnecessary memory consumption.
hope it helped someone.
You don't say how you load the background.
But, if you've simply just set in the fragment layout then the image gets loaded when you inflate the XML. This happens in the UI thread. The larger the image the longer it takes.
I would recommend loading images with an async library like Picasso.
I had the same problem. First I thought the data size of the image was to big but that wasn't the case. I changed the measurement of the image in Photoshop and decreased the width. Now it works fine.

Inconsistency errors between android.support.v4.app and android.app

I'm trying to create an activity that shows some fragments. I'm following this example here: http://developer.android.com/training/animation/screen-slide.html, however there seems to be some missing code / inconsistencies. I've narrowed down many of the problems but I'm stuck on one part, though it seems it would be simple to someone that knows how this works.
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm); // error on fm
}
error underlines fm on super(fm);: "FragmentStatePagerAdapter (android.support.v4.app.FragmentManager) in FragmentStatePagerAdapter cannot be applied to (android.app.FragmentManager)"
#Override
public Fragment getItem(int position) { // error on Fragment
return ScreenSlidePageFragment.create(position);
}
error underlines Fragment on public Fragment getItem(int position) {: 'getItem(int)' in 'com.example.Application.ScreenSlideActivity.ScreenSlidePagerAdapter' clashes with 'getItem(int)' in 'android.support.v4.app.FragmentStatePagerAdapter'; attempting to use incompatible return type
ScreenSlideActivity.java:
package com.example.dgzl.corvegas;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.NavUtils;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
/**
* Demonstrates a "screen-slide" animation using a {#link ViewPager}. Because {#link ViewPager}
* automatically plays such an animation when calling {#link ViewPager#setCurrentItem(int)}, there
* isn't any animation-specific code in this sample.
*
* <p>This sample shows a "next" button that advances the user to the next step in a wizard,
* animating the current screen out (to the left) and the next screen in (from the right). The
* reverse animation is played when the user presses the "previous" button.</p>
*
* #see ScreenSlidePageFragment
*/
public class ScreenSlideActivity extends android.support.v4.app.FragmentActivity {
/* The number of pages (wizard steps) to show in this demo.*/
private static final int NUM_PAGES = 3;
/* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.*/
private ViewPager mPager;
/* The pager adapter, which provides the pages to the view pager widget.*/
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// When changing pages, reset the action bar actions since they are dependent
// on which page is currently active. An alternative approach is to have each
// fragment expose actions itself (rather than the activity exposing actions),
// but for simplicity, the activity provides the actions in this sample.
invalidateOptionsMenu();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.activity_screen_slide, menu);
menu.findItem(R.id.action_prev).setEnabled(mPager.getCurrentItem() > 0);
// Add either a "next" or "finish" button to the action bar, depending on which page
// is currently selected.
MenuItem item = menu.add(Menu.NONE, R.id.action_next, Menu.NONE,
(mPager.getCurrentItem() == mPagerAdapter.getCount() - 1)
? "action_finish"
: "action_next");
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// Navigate "up" the demo structure to the launchpad activity.
// See http://developer.android.com/design/patterns/navigation.html for more.
NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class));
return true;
case R.id.action_previous:
// Go to the previous step in the wizard. If there is no previous step,
// setCurrentItem will do nothing.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
return true;
case R.id.action_next:
// Advance to the next step in the wizard. If there is no next step, setCurrentItem
// will do nothing.
mPager.setCurrentItem(mPager.getCurrentItem() + 1);
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A simple pager adapter that represents 5 {#link ScreenSlidePageFragment} objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return ScreenSlidePageFragment.create(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
ScreenSlidePageFragment.java"
package com.example.Application
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class ScreenSlidePageFragment extends Fragment {
public static final String ARG_PAGE = "page";
private int mPageNumber;
public static ScreenSlidePageFragment create(int pageNumber) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
public ScreenSlidePageFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout containing a title and body text.
ViewGroup rootView = (ViewGroup) inflater
.inflate(R.layout.fragment_today, container, false);
// Set the title view to show the page number.
((TextView) rootView.findViewById(android.R.id.text1)).setText(
getString(R.string.title_template_step, mPageNumber + 1));
return rootView;
}
/**
* Returns the page number represented by this fragment object.
*/
public int getPageNumber() {
return mPageNumber;
}
}
You must import Fragment and FragmentManager class from support library please change your first two lines of import like below in your ScreenSlideActivity class
import android.support.v4.app.FragmentManager
import android.support.v4.app.Fragment

Android how to stop refreshing Fragments on tab change

I have the following code :
MainActivity.java
package com.erc.library;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import com.erc.sayeghlibrary.adapter.TabsPagerAdapter;
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Stories", "Dictionaries", "eBooks"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int actionBarTitleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
if (actionBarTitleId > 0) {
TextView title = (TextView) findViewById(actionBarTitleId);
if (title != null) {
title.setTextColor(Color.WHITE);
}
}
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// action with ID action_refresh was selected
case R.id.Favorites:
Toast.makeText(this, "Favorites selected", Toast.LENGTH_SHORT)
.show();
break;
// action with ID action_settings was selected
default:
break;
}
return true;
}
}
TabsPagerAdapter.java
package com.erc.library.adapter;
import com.erc.library.Dictionaries;
import com.erc.library.Ebooks;
import com.erc.library.Stories;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new Stories();
case 1:
return new Dictionaries();
case 2:
// Movies fragment activity
return new Ebooks();
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
I'm making a library application in which the navigation is by tabs, the problem is each time I go from the third tab to the first or the first to the third, the tab content is refreshing, I want to prevent the refresh, Any help please ?
By default, ViewPager recreates the fragments when you swipe the page. To prevent this, you can try one of three things:
1. In the onCreate() of your fragments, call setRetainInstance(true).
2. If the number of fragments is fixed & relatively small, then in your onCreate() add the following code:
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(limit); /* limit is a fixed integer*/
3. Use a FragmentPagerAdapter as part of your ViewPager.
If I remember correctly, the second option is more promising. But I urge you to try all three and see which of them work.
one has to instance the FragmentPagerAdapter first, then .getCount() will return a value -
while .getCount() - 1 should be set as the default off-screen limit:
TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager());
/* the ViewPager requires a minimum of 1 as OffscreenPageLimit */
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);
you can handle view recreation by check if the view is null or not
public class FragmentExample extends Fragment {
private View rootView;
public FragmentExample() {}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
if (rootView == null) {
rootView = inflater.inflate(R.layout.fragment_example_layout, container, false);
// Initialise your layout here
} else {
((ViewGroup) rootView.getParent()).removeView(rootView);
}
return rootView;
}
}
In the onCreate() of your fragments, call setRetainInstance(true)
A bit late to this question, but thanks to Y.S., got to know how ViewPager works. I was building an app with 4 tabs and at any point of time, noticed that only two tabs were being refreshed, which I suppose was a default behaviour. After hours of investigation, I understood that Android refreshes multiple tabs to bring in a smooth swiping performance for the user - you might notice that you would have clicked tab2, but android brings in the data for tab3 and keeps it ready.
Though this behaviour is good, it has its pros and cons. Pros - you get a smooth swiping experience, without data being loaded from an external server when you land up in that tab. Cons-your backstack implementation in tabs could go for a toss. When you click a tab, the view pager actually calls smoother tab and you'll end up in a big trouble, if your methods are setting up backarrow (home) at the top left based on what is in the backstack in the clicked tab.
setOffscreenPageLimit is the answer to this. If you want your custom backstack framework to function, and do not want tab3 to be called when tab2 is clicked, you simply need to set the value to the number of tabs. For instance, if you have 4 tabs, set setOffScreePageLimit(4). This would mean that Android would refresh all the 4 fragments initially, which is a bit of a performance overhead (which you should manage properly). But, your backstack and tab switching remain intact. Hope this helps.
Since the activity implements ActionBar.TabListener, the activity's onCreate() is getting called again and again. So place the following code in onResume() method:
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
In my case above suggestion does not work.
To restrict recreation of fragment, what i did:
In onCreateView you can store inflated view in a global variable and initialize it only if it is null, like in this code:
var root:View?=null
var apiDataReceived=false
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
if (root==null)
root=inflater!!.inflate(R.layout.fragment_layout, container, false)
return root
}
Now if you are parsing some data and fill it into RecyclerView or any other View
Make a global variable like in above code apiDataReceived
Set it to true if you successfully parsed data.
Before apiCalls place a condition like this:
if (!apiDataReceived) {
apiCalls()
}
So if apiCalls() would be called only if data is not parsed.
Do your http calls and parsing or any other thing in method which called after onCreateView like onStart
The above code is in kotlin, If you are facing any issue, let me know in comments.

Constructor within activity is undefined

I have been fighting with this error for a couple of hours and I am not able to continue. I need your help here!
I am trying to replace my previous TabNavigation at ActionBar by a ViewPager in SDK21, looking at comments within StackOverflow I found this webpage, where the use of PagerTabStrip is described with an example, so I tried to implement it in my activity, however I am getting an strange error.
I tried to google the problem and all the suggestions are not really applicable to my problem (wrong parameters in the constructor are the usual errors) . I also reproduced the error with a simple Activity in order to avoid anything I have in my previous activity, but the error keeps. I attach you here the code I replicated isolated:
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TestActivity extends Activity {
CustomPagerAdapter mCustomPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adding_users_to_list);
mCustomPagerAdapter = new CustomPagerAdapter(getFragmentManager(), this.getApplicationContext());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mCustomPagerAdapter);
}
class CustomPagerAdapter extends FragmentPagerAdapter {
Context mContext;
public CustomPagerAdapter(FragmentManager fm, Context context) {
super(fm);
mContext = context;
}
#Override
public Fragment getItem(int position) {
// Create fragment object
Fragment fragment = new DemoFragment();
// Attach some data to the fragment
// that we'll use to populate our fragment layouts
Bundle args = new Bundle();
args.putInt("page_position", position + 1);
// Set the arguments on the fragment
// that will be fetched in the
// DemoFragment#onCreateView
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return "Page " + (position + 1);
}
}
class DemoFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout resource that'll be returned
View rootView = inflater.inflate(R.layout.fragment_users, container, false);
// Get the arguments that was supplied when
// the fragment was instantiated in the
// CustomPagerAdapter
Bundle args = getArguments();
((TextView) rootView.findViewById(R.id.text_option)).setText("Page " + args.getInt("page_position"));
return rootView;
}
}
}
I am getting in the call to the constructor the following error:
"The constructor TestActivity.CustomePageAdapter(FragmentManager, Context) is undefined"
In here:
mCustomPagerAdapter = new CustomPagerAdapter(getFragmentManager(), this.getApplicationContext());
I have tried to introduce the Adapter outside and inside the activity definition and is still not working. Is likely to be something simple, but... I can't see it and I need other eyes. Any idea what I am doing wrong?
change the import of the activity to:
import android.support.v4.app.FragmentActivity;
Also change constructor to:
mCustomPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager(), this.getApplicationContext());
The reason is that your activity is used from the ADT:
import android.app.Activity;
and the Fragments used from the support package:
import android.support.v4.app.FragmentManager;
change the import of the activity to:
import android.support.v4.app.FragmentActivity;

The return type is incompatible with FragmentPagerAdapter.getItem(int) More errors

I am receiving The return type is incompatible with FragmentPagerAdapter.getItem(int) for public void Fragment getItem(int position) at the bottom of the code. Error is coming from Fragment.
I have found some related topics on this error and I have tried to do them to fix the issue but nothing seems to solve the error or rather it fixes one error then 5 other errors open up, I try to fix those and again 30 errors open up. Any ideas?
I have changed import android.app.Fragment; to import android.support.v4.app.Fragment; and some other import changes and have gotten it down to this one error. Any help would be greatly appreciated. Thanks!
I included most of the code as I am not sure if I am making errors elsewhere. I believe it has to do with the import but I've tried many diff combinations and no luck.
package com.example.hellofragsandwich;
import java.util.Locale;
import android.app.Activity;
import android.app.ActionBar;
import android.support.v4.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v4.app.FragmentPagerAdapter;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends FragmentActivity implements ActionBar.TabListener, Communicator {
public final int TOTAL_FRAGMENTS=7;
Fragment fragment_0 = new Fragment_0();
Fragment fragment_1 = new Fragment_1();
Fragment fragment_2 = new Fragment_2();
Fragment fragment_3 = new Fragment_3();
Fragment fragment_4 = new Fragment_4();
Fragment fragment_5 = new Fragment_5();
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class
// below).
Fragment fragment = null;
switch (position) {
case 0:
return fragment_0;
case 1:
return fragment_1;
case 2:
return fragment_2;
case 3:
return fragment_3;
case 4:
return fragment_4;
case 5:
return fragment_5;
case 6:
return fragment_6;
}
return fragment;
}
}
If you are using import android.support.v13.app.FragmentPagerAdapter; from v13 support library you should use android.app.Fragment not v4 one. (with v13 you should use getFragmentManager())
Or if you want to use android.support.v4.app.Fragment you should use android.support.v4.app.FragmentPagerAdapter not v13 one (with v4 fragment you should use getSupportFragmentManager())

Categories