How to refresh the Pager tab fragment in android? - 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
}
}
}

Related

What thread which Android use when fragment recreate from scratch?

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
}

Android Fragment Data Pass with TABBED Activity

When i try to retrieve category list from server for multiple tab, after set adapter its Toast two ID for the first time .Suppose, When current tab id is ZERO , then its showing next increment ID .
Like the Screenshot its showing 20 in tab 0 .
Basically i want the category id dynamically when i swipe the tab.
public class Tabtest extends AppCompatActivity {
TabLayout tabLayout;
ViewPager viewPager;
Toolbar toolbar;
int i;
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
#SuppressLint("WrongViewCast")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabtest);
toolbar=(Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabLayout=(TabLayout)findViewById(R.id.tabs);
viewPager=(ViewPager)findViewById(R.id.container);
getCategoriesList();
tabLayout.setupWithViewPager(viewPager);
}
public void getCategoriesList(){
Retrofit retrofit = newsClient.getClient();
apiNews service = retrofit.create(apiNews.class);
Call<List<Category>> call = service.categorriesList();
call.enqueue(new Callback<List<Category>>() {
#Override
public void onResponse(Call<List<Category>> call, Response<List<Category>> response) {
if (response.isSuccessful()){
for (int i=0;i<response.body().size();i++){
MenuBurgersFragment pageFragment= new MenuBurgersFragment();
Bundle bundle = new Bundle();
adapter.addFragment(pageFragment, response.body().get(i).getId()+"");
bundle.putString("welcome", response.body().get(i).getId()+"" );
viewPager.setAdapter(adapter);
pageFragment.setArguments(bundle);
adapter.notifyDataSetChanged();
}
}
}
#Override
public void onFailure(Call<List<Category>> call, Throwable t) {
Toast.makeText(Tabtest.this, "safsavas", Toast.LENGTH_SHORT).show();
}
});
}
}
ViewPagerAdapter
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);
}
}
Fragment
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_menu_list_items, container, false);
bundle = this.getArguments();
if(bundle!=null) {
storeText = bundle.getString("welcome");
Toast.makeText(getContext().getApplicationContext(), storeText, Toast.LENGTH_SHORT).show();
}
In View Pager Bydefault previous and next fragment data is loaded that's why you got next fragment value in toast .
In that you have to set OffscreenPageLimit in viewpager to restrict to load previous and next fragment in View Pager
set value of setOffscreenPageLimit() is 1 .
Hope that above will help you.

FragmentManager is already executing transactions. While using fragment in android

Iam using a Viewpager inside a fragment. And the viewpager is initialized after the fragment is created. The viewpager has two tabs.
But while i am setting the adapter for the viewpager "FragmentManager is already executing transactions." this error comes up.
Error is as follows.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.lalrentals.app.lalrentals, PID: 26248
java.lang.IllegalStateException: FragmentManager is already executing transactions
Java class :
public class HomeFr extends Fragment
{
public HomeFr(){
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//ADDING VIEWPAGER
ViewPager viewPager = getActivity().findViewById(R.id.viewpager);
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new HomeFr(), "Home");
adapter.addFragment(new PostAddFr(), "Post");
viewPager.setAdapter(adapter);
//SETTING TAB FOR THE VIEWPAGER
TabLayout tabLayout = getActivity().findViewById(R.id.tab);
tabLayout.setupWithViewPager(viewPager);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = LayoutInflater.from(getActivity()).inflate(R.layout.frag_home,null);
return v;
}
//ADAPTER FOR THE VIEWPAGER
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#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'm not totally sure if this is the root cause but I think following point is wrong:
adapter.addFragment(new HomeFr(), "Home");
adapter.addFragment(new PostAddFr(), "Post");
Inside HomeFr fragment you are adding HomeFr again. Instead, you should have a "generic" Fragment which will host HomeFr and PostAddFr.
So, in the end, you should have 3 fragments:
Host which will be the parent Fragment and this fragment is responsible to instantiate the view pager
HomeFr one of the Fragments displayed by the view pager
PostAddFr one of the Fragments displayed by the view pager
Something like:
HostFr
public class HostFr extends Fragment {
public HostFr(){
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
....
adapter.addFragment(new HomeFr(), "Home");
adapter.addFragment(new PostAddFr(), "Post");
....
}
.....
class ViewPagerAdapter extends FragmentPagerAdapter {
....
}
}
HomeFr
public class HomeFr extends Fragment {
...
// HomeFr Views
...
}
PostAddFr
public class PostAddFr extends Fragment {
...
// PostAddFr Views
...
}

Fragment not restoring edittext value after swapping back in view_pager

first fragment not restoring edit box value after swapping 3 fragment in viewPager... i have 3 fragment inside viewpager and after clicking on 3rd fragment tab and swap back to 1st fragment .. edit text filling blank.. plz give some solutions.. code is here..
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_item_master, container, false);
viewPager = (ViewPager)v. findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout)v. findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
return v;
}
private void setupViewPager(ViewPager viewPager) {
// ViewPagerAdapter adapter = new ViewPagerAdapter(mActivity.getSupportFragmentManager());
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new ItemInfoFragment(), "Item Info");
adapter.addFragment(new ItemExtraInfoFragment(), "Extra Info");
adapter.addFragment(new OrderHistoryFragment(), "Order History");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentStatePagerAdapter {
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);
}
This is recommended only if you have less number of fragments. You can use yourViewPager.setOffscreenPageLimit(numberOfFragmentsInViewPager);What this does is it wont create a new fragment every time you swipe, thus data is persisted. the default value will be 1 if you won't set this property.

fragment in view pager generate fatal error on activity restart

I have an activity that show data stored in database in a view pager organized in fragments.
When the adapter init the View Pager it call a method in each fragment to pass the id of the database entry to retrive and show:
public Fragment getItem(int position) {
switch (position) {
case 0: // Fragment # 0 - This will show FirstFragment different title
firstFragment = Fragment.newInstance(1, "Page # 1");
firstFragment.setID(ctx, id);
return firstFragment;
case 1: // Fragment # 0 - This will show FirstFragment different title
secondFragment = Fragment.newInstance(1, "Page # 2");
secondFragment.setID(ctx, id);
return secondFragment;
case 2: // Fragment # 0 - This will show FirstFragment
thirdtFragment = Fragment.newInstance(1, "Page # 3");
thirdtFragment.setID(context, id);
return thirdtFragment;
default:
return null;
}
}
when the method onCreateView of the fragment get called it retrive the data from the database and init all the view displaying the data to the user:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
DataManager dataManager = new DataManager(mContext);
DataModel data = dataManager.getData(mID);
.....
All seems to work fine except when the user restart the app that was for example paused when inside this activity: when the activity got restarted I get a fatal error accessing the data, as if the private variable (of the fragment) containing the ID of the data got deleted from the garbage collector.
Is my approach correct? How can I prevent the error generated when the activity get restarted?
During onPause and onResume Fragment and Activity is managed by android so you may not retrieve the member variables so to overcome this problem on your Fragment's newInstance method use something like
public static Fragment newInstance(int id, String page){
Bundle bundle = new Bundle();
bundle.putString("page", page);
bundle.putInt("ID", page);
setArguments(bundle);
}
and on your onCreateView callback use something like
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
int mID = getArguments().getInt("ID");
DataManager dataManager = new DataManager(mContext);
DataModel data = dataManager.getData(mID);
...
So, I approached my problem by doing the following:
Create a view pager that has a list of Fragments and their respective titles. This view pager adapter should have a method to add fragments to the list. Here is my code:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
private int mItemId;
public ViewPagerAdapter(FragmentManager manager, int id) {
super(manager);
mItemId = id;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
Bundle bundle = new Bundle();
bundle.putInt("itemId", mItemId);
fragment.setArguments(bundle);
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}}
Now, inside your Fragment, you can extract the bundle extra which can help you when reading some data from your database for example if it is an id for table column. This could be your fragment class:
public class InfoFragment extends Fragment {
private Activity mActivity;
private CustomerDbObject customer;
private int customerId;
public InfoFragment() {
// Required empty public constructor
}
#Override
public void onAttach(Context ctx){
super.onAttach(ctx);
if (ctx instanceof Activity){
this.mActivity = (Activity) ctx;
}
customerId = getArguments().getInt("itemId");
Realm realm = Realm.getInstance(ctx);
RealmQuery<Customer> query = realm.where(Customer.class);
query = query.equalTo("account_id", customerId);
customer = query.findFirst();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.customer_fragment_info, container, false);
ButterKnife.bind(this, view);
return view;
}}
With these two pieces in place, what we need now is our activity that will display the viewpager with tabs! Remember, it is inside this same activity that we provide the extra (itemId) to the viewpager instance then the viewpager will pass it to the fragment in that order.
public class CustomerActivity extends AppCompatActivity {
private int mSelectedCustomer = 5; //this value could be extracted for an intent that is passed from a Recyclerviewer etc
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer_details);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
final ViewPager mViewPager = (ViewPager) findViewById(R.id.viewPager);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), mSelectedCustomer);
adapter.addFrag(new InfoFragment(), getString(R.string.info_tab));
}
}
Now that we have all the pieces together, the important extra (data) being passed around should always be available to the Fragment through the viewpager adapter which gets it subsequently from the activity.
When I tested this, it worked and I hope it works for you as well. Please let me know how it goes!!

Categories

Resources