What thread which Android use when fragment recreate from scratch? - android

I have a ViewPager.When some data changed,i set the adapter for the ViewPager again by call ViewPager.setAdapter(new Adapter).What i wonder is,the Fragment is re-create (it jump on onDestroyView and then onCreateView) and my Edittext cannot set again the text.And if i remove all Fragment from FragmentTransaction and then setAdapter,the Fragment create a new one -> my Edittext set the text well.So is Fragment recreate itselft NOT from UI thread? ( Because i try the edditext.post and my edditext from first scenario work).Here is the code
Adapter:
public class PagerAdapter extends FragmentPagerAdapter {
private final ArrayList<Fragment> fmAct;
public PagerAdapter(FragmentManager supportFragmentManager, ArrayList<Fragment> fm) {
super(supportFragmentManager);
fmAct = fm;
}
#Override
public Fragment getItem(int position) {
return fmAct.get(position);
}
#Override
public int getCount() {
return fmAct.size();
}
#Override
public int getItemPosition(#NonNull Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
return ((PrFragment) getItem(position)).getFragmentName();
}
what i do when re-set the adapter
fm.clear();
fragmentAttendanceCome = new FragmentAttendanceCome();
fragmentAttendanceCome.setFragmentName(getString(R.string.title_attendance));
fragmentAttendanceCome.setParentActivity(this);
fragmentAssessment = new FragmentAssessment();
fragmentAssessment.setFragmentName(getString(R.string.daily_evaluation));
fragmentAssessment.setParentActivity(this);
fragmentInfo = new FragmentInfo();
fragmentInfo.setParentActivity(this);
fragmentInfo.setFragmentName(getString(R.string.title_infomation));
fm.add(fragmentAttendanceCome);
fm.add(fragmentAssessment);
fm.add(fragmentInfo);
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager(), fm));
This is my fragment :
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
textview.setText(data)
// i already Bind it but i lazy to copy it,everything work well
}

Related

Refresh current fragment in tabbed layout viewpager

I am trying to refresh the current fragment in the tabbed layout of my viewpager. I have one fragment (UserProgressFragment) that creates the ViewPager and sets the adapter (UserProgressAdapter) along with creating tabbed layout.
In my UserProgressAdapter, in the getItem() method I am returning two other fragments, (UserWeightTrackerFragment and UserCalorieCounterFragment) based on which tab i am on.
My issue is how do i refresh the fragment and update its content/view from the UserCalorieCounterFragment on a button click, because access to the viewpager and adapter are set in the UserProgressFragment? I have considered notifyDataChange for the adapter but i dont know how to call this from this class as it is set up on the UserProgressFragment class. The purpose of wanting to refresh this page is to update a specific view which is a chart, if context is needed.
I have attached the code below:
UserProgressFragment
public class UserProgressFragment extends Fragment{
public static UserProgressFragment newInstance() {
return new UserProgressFragment();
}
public UserProgressFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_user_progress, container, false);
ViewPager viewPager = view.findViewById(R.id.progress_viewpager);
viewPager.setAdapter(new UserProgressTabsAdapter(getChildFragmentManager()));
TabLayout tabLayout = view.findViewById(R.id.progress_sliding_tabs);
tabLayout.setupWithViewPager(viewPager, true);
return view;
}
}
UserProgressTabsAdapter
public class UserProgressTabsAdapter extends FragmentStatePagerAdapter {
private static final int PAGE_COUNT = 2;
private String tabTitles[] = new String[]{"Weight Tracker", "Calorie Counter"};
public UserProgressTabsAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return UserWeightTrackerFragment.newInstance(position);
case 1:
return UserCalorieCounterFragment.newInstance(position + 1);
}
return null;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
UserCalorieCounterFragment (need to refresh this one)
public class UserCalorieCounterFragment extends Fragment implements View.OnClickListener, AdapterView.OnItemSelectedListener {
public static final String ARG_PAGE = "ARG_PAGE";
public static UserCalorieCounterFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
UserCalorieCounterFragment fragment = new UserCalorieCounterFragment();
fragment.setArguments(args);
return fragment;
}
public UserCalorieCounterFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int mPage = getArguments().getInt(ARG_PAGE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_user_calorie_counter, container, false);
Button mAddCalories = view.findViewById(R.id.btn_add_calorie);
mAddCalories.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_add_calorie:
//REFRESH/UPDATE HERE
break;
}
}
You can create a public method in your fragment which contains the view pager which will contain the notifyDataSetChanged() function. And in the view pager fragment/item, you can call getParentFragment() and type cast it to your parent/first fragment and access that public method to notifyDataSetChanged().

How to refresh the Pager tab fragment in android?

I have to refresh the fragment when I swipe to another fragment from the Tab.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mBinding = DataBindingUtil.inflate(inflater, R.layout.manage_work_shop_act, container, false);
mBinding.layout.title.setText(getString(R.string.d_manage_my_staff));
mBinding.tabs.setupWithViewPager(mBinding.viewpager);
setupViewPager(mBinding.viewpager);
mBinding.layout.nav.setVisibility(View.GONE);
mBinding.layout.navMenu.setVisibility(View.VISIBLE);
mBinding.layout.navMenu.setOnClickListener(view -> openDrawer());
return mBinding.getRoot();
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);
adapter.addFragment(new MechanicListFragment(), getString(R.string.d_manage_my_staff));
adapter.addFragment(new MechanicNewFragment(), getString(R.string.new_frag));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);
adapter.notifyDataSetChanged();
}
My Adapter is like this
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I tried all the ways to refresh my fragment.
If I swipe the tab or click the another tab then I need to refresh the visible tab again.
In my current fragment did not refresh.
please help me to override from this issue.
Try using Fragment state pager adapter than fragment adapter when you have to refresh tabs in your adapdter.
FragmentPagerAdapter stores the previous data which is fetched from the adapter while FragmentStatePagerAdapter takes the new value from the adapter everytime it is executed.
There's onHiddenChanged method in the fragment.
Called when the hidden state (as returned by isHidden() of the
fragment has changed. Fragments start out not hidden; this will be
called whenever the fragment changes state from that.
override the onHiddenChanged method in each of your tab fragment and if is not hidden do the refreshing. For example:
class YourFragment extends Fragment {
#Override public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
//you can refresh here now
}
}
}

getItem in FragmentStatePagerAdapter never called when instantiating from a Fragment

I'm using a Fragment on my Activity that will have a picture "swiper". I've created a FragmentStatePagerAdapter which I'm trying to call from this Fragment and for some reason my getItem() method is never being called.
I've searched and found that I need to use getChildFragmentManager() when instantiating my FragmentStatePagerAdapter because I'm calling it from a Fragment. I've tried this as well as getSupportFragmentManager() with no luck from either.
Any ideas?
here's my Fragment that I'm using on my MainActivity with the method that shoudl setup the FragmentStatePagerAdapter:
public class PhotoFlipper extends Fragment {
// properties and fields
// primitive types
String currentImage;
int friendShareType = 0;
ImageView share;
ViewPager pager;
PhotoFlipperItemAdapter pagerAdapter;
LatLng itemPosition;
Activity activity;
FragmentActivity fragActivity;
public ArrayList<MarkerModel> picsAndVids;
// end properties and fields
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View photoFlipperFragmentView = inflater.inflate(R.layout.photo_flipper_layout, container, false);
InitializeFragment(photoFlipperFragmentView);
return photoFlipperFragmentView;
}
private void InitializeFragment(View photoFlipperFragmentView) {
activity = getActivity();
fragActivity = (FragmentActivity)activity;
pager = (ViewPager)photoFlipperFragmentView.findViewById(R.id.photoflipper_pager);
share = (ImageView)photoFlipperFragmentView.findViewById(R.id.photoflipper_share);
share.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
IPictureFlipper iPictureFlipper = (IPictureFlipper)activity;
iPictureFlipper.ShareVideoOrImage(friendShareType, itemPosition, currentImage);
}
});
}
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
pager.setVisibility(View.GONE);
}
}
public void SetTappedPicture(int index) {
pagerAdapter = new PhotoFlipperItemAdapter(getChildFragmentManager(), picsAndVids, picsAndVids.size());
pager.setAdapter(pagerAdapter);
pager.setCurrentItem(index);
pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
});
}
}
And here's my FragmentStatePagerAdapter:
public class PhotoFlipperItemAdapter extends FragmentStatePagerAdapter {
ArrayList<MarkerModel> _markers;
int NUM_PAGES;
String TAG = "home";
public PhotoFlipperItemAdapter(FragmentManager fm, ArrayList<MarkerModel> markers, int numpages){
super(fm);
Log.d(TAG,"in adapter in constructor");
_markers = markers;
NUM_PAGES = numpages;
}
#Override
public Fragment getItem(int position) {
Log.d(TAG,"in adapter in get item");
Fragment fragment = PhotoFlipperItemFragment.create(position, _markers);
return fragment;
}
#Override
public int getCount() {
Log.d(TAG,"in adapter in get count: "+NUM_PAGES);
return NUM_PAGES;
}
}
logcat is showing me that NUM_PAGES is > 0 so that's not my issue. I see my log in the constructor and in getCount() but nothing in getItem().
TIA
I got this sorted out. I was hiding my fragment in my InitializeActivity() right after I added it to my FragmentManager so it was never fully building the Fragment with the ViewPager etc.
I'm going to have to come up with a different solution for hiding/showing the fragment but that was my problem.

FragmentManager contains fragment from viewpager after state loss

On state loss or screen rotation and when my boolean flag is true, I want to recreate my screen. However, the fragment manager still has the previous fragment attached and it gets loaded.
What can I do to get rid of that fragment?
public class ViewPagerAdapter extends FragmentPagerAdapter {
private String[] mData;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
mData= new String[0];
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putInt("key", position);
Fragment fragment = new MyFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return mData.length;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
return mData[position];
}
public void setData(String[] data) {
mData= data;
}
}
Piece of code in Activity onCreate()
mViewPagerAdapter = new ViewPagerAdapter(getFragmentManager());
mViewPagerAdapter.setData(data);
viewPager.setAdapter(mViewPagerAdapter);
You may override instantiateItem() to detect screen rotation like a Fragment can.
Code example:
#Override
public boolean isViewFromObject(View view, Object o) {
return o == view;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,
container, false);
return view;
}
Note: instantiateItem() occurs upon screen rotation. Activity does not detect that. The hint is that the class does not have onCreateView() like the fragment class.

Viewpager + FragmentStatePagerAdapter + Fragment not working

I have a FragmentList with some items. If I click an item the appropriate Fragment will open which contains a Viewpager. No problem so far but if I go back to the List and click the item again the method getItem(int position) is not called anymore.
Here a link with a similar problem:
Display fragment viewpager within a fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_fragment_runtime, container, false);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
indicator = (TitlePageIndicator) view.findViewById(R.id.indicator);
MyFragmentPagerAdapter mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getActivity().getSupportFragmentManager());
mViewPager.setAdapter(mMyFragmentPagerAdapter);
indicator.setViewPager(mViewPager);
return view;
}
class MyFragmentPagerAdapter extends FragmentStatePagerAdapter implements TitleProvider {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public String getTitle(int position) {
return muxbusTitles[position];
}
#Override
public Fragment getItem(int location) {
return muxbusFragmentList.get(location);
}
#Override
public int getCount() {
return muxbusTitles.length;
}
}
return view;
}
Edit:
If someone is interested,the solution was to extends from PagerAdapter instead of FragmentStatePagerAdpater because the Viewpager is already in a Fragment..
I did have similar problem and after scratching my head for quite some time i made an my own understanding (assumption) that ViewPager is keeping the reference of its child fragments into memory even the hosted Fragment or Activity is destroyed (didn't tested with Activity). So i wrote this method freeFragmentsFromViewPager(). You need to call it from onDestroy() of your Fragment.
/**
* This method free the child fragments from ViewPager as ViewPager keeps the reference
* of child fragments into memory and next time when you again come to visit view pager it won't show the fragment layout
* because it has the reference to the fragment whilst the fragment's view was already destroyed.
*/
private void freeFragmentsFromViewPager()
{
for(int i = 0; i < TabsFragmentPagerAdapter.fragments.length; i++)
{
Fragment fragment = TabsFragmentPagerAdapter.fragments[i];
if(fragment != null)
{
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
TabsFragmentPagerAdapter.fragments[i] = null;
}
}
}
And this is my Adapter code
public class TabsFragmentPagerAdapter extends FragmentPagerAdapter
{
public static final int NUM_TABS = 3;
public static Fragment[] fragments = new Fragment[NUM_TABS];
public TabsFragmentPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position)
{
Log.e("TabsFragmentPagerAdapter", "getItem");
Fragment fragment = TabsFragmentFactory.newInstace(position);
fragments[position] = fragment;
return fragment;
}
#Override
public int getCount()
{
return NUM_TABS;
}
#Override
public CharSequence getPageTitle(int position)
{
return TabsFragmentFactory.getName(position);
}

Categories

Resources