Blank Fragment inside Tablayout / Viewpager - android

So i'm desperately looking for an answer to my problem. I spend hours try and retry some things but that did not work.
So here is my problem :
I have only one activity for my application which is the main activity.
This activity contains a bottom navigation bar and a frame layout to load a fragment depending the choice of the item on the bottom navigation bar.
My PredictionsFragment (loaded by bottom navigation bar) contains a TabLayout (using SmartTabLayout library). In this Fragment, a list of data is loaded in a thread because it use internet connection. TabLayout is containing PredictionsViewFragment which displays a RecyclerView.
When I select the PredictionsFragment on my bottom navigation bar, tablayout and all the recyclerview are perfectly displayed.
But when I go to another item and go back to PredictionsFragment it displays a blank view...
PredictionsFragment code :
public class PredictionsFragment extends Fragment {
private static List<Country> countryList = new ArrayList<>();
private ViewPager viewPager;
private SmartTabLayout viewPagerTab;
private FragmentStatePagerItemAdapter adapter;
private FragmentPagerItems pages;
private ProgressBar progressBar;
private ViewGroup tab;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_predictions_tab, container, false);
initView(view);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (countryList.size() == 0) {
refresh();
} else {
refreshViewPager();
}
}
private void initView(View view) {
tab = (ViewGroup) view.findViewById(R.id.tab);
tab.addView(LayoutInflater.from(getContext()).inflate(R.layout.fragment_view_predictions, tab, false));
progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPagerTab = (SmartTabLayout) view.findViewById(R.id.viewpagertab);
viewPager.setOffscreenPageLimit(countryList.size());
pages = new FragmentPagerItems(getContext());
adapter = new FragmentStatePagerItemAdapter(getFragmentManager(), pages){
public int getItemPosition(Object object) {
return POSITION_NONE;
}
};
viewPager.setAdapter(adapter);
viewPagerTab.setViewPager(viewPager);
}
private void refresh() {
// Thread car connexion internet
new Thread(new Runnable() {
#Override
public void run() {
countryList = InternetData.getCountryList();
refreshViewPager();
}
}).start();
}
private void refreshViewPager() {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
for (Country country : countryList) {
pages.add(FragmentPagerItem.of(country.getCode(), PredictionsViewFragment.class));
}
adapter.notifyDataSetChanged();
viewPagerTab.setViewPager(viewPager);
progressBar.setVisibility(View.GONE);
}
});
}
public static List<Prediction> getPredictionList(int index) {
return countryList.get(index).getPredictionList();
}
}
PredictionsViewFragment code :
public class PredictionsViewFragment extends Fragment {
private RecyclerView recyclerView;
private PredictionAdapter adapter;
private int position;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recycler_view_pronos, container, false);
position = FragmentPagerItem.getPosition(getArguments());
initRecyclerView(view);
return view;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private void initRecyclerView(View view) {
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
adapter = new PredictionAdapter(PredictionsFragment.getPredictionList(position));
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter);
}
}
Screenshot of the blank fragment and the app
EDIT :
When I use getChildFragmentManager() method :
adapter = new FragmentStatePagerItemAdapter(getChildFragmentManager(), pages){
public int getItemPosition(Object object) {
return POSITION_NONE;
}
};
I get this error when I go the second time on the Fragment (The first time I go on it, it works perfectly) :
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:936)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:217)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1461)
at android.view.View.dispatchRestoreInstanceState(View.java:18608)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3821)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3827)
at android.view.View.restoreHierarchyState(View.java:18586)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:494)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1486)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
EDIT 2 :
I added these lines to the onViewCreated method on my PredictionsFragment :
else {
refreshViewPager();
}
But it does absolutely nothing... The name of the tab appears properly but not the recyclerview...
It's like the Fragment inside the tablayout isn't loaded
EDIT 3 :
I have added a SwipeRefreshLayout to my recyclerview and for the 2 first tabs i can't do a pull to refresh and from the 3rd tabs only one item of the recyclerview appears and pull to refresh "works" but it displays only one item in the recyclerview
If you have any questions tell me I'll do my best to answer it !
Thanks in advance for you help I appreciate it

Use setOffsetScreenPageLimit in viewPager: This will help you to store the data in the pagers fragments when you navigate through bottom tabs.
viewPager.setOffscreenPageLimit(the number of tab you are setting);
For refreshing the data in recycler view you can use "Swipe refresh"

So I solved my problem...
You have to use this :
adapter = new FragmentPagerItemAdapter(getChildFragmentManager(), pages);
Use FragmentPagerItemAdapter and NOT FragmentStatePagerItemAdapter
And for sur you have to use getChildFragmentManager()

I was also using BottomNavigationView to open tabLayout with viewPager & faced the same problem. FragmentStatePagerAdapter can be used for this.
This class handles saving and restoring of fragment's state -> It's in the documentation

Related

RecyclerView is a null in fragment

I have MainActivity,which contain viewpager,which contain 2 fragments:
MainActivity
ViewPager viewPager = findViewById(R.id.viewPager);
MyPagerAdapter adapter = new MyPagerAdapter(this,
getSupportFragmentManager());
viewPager.setAdapter(adapter);
TabLayout tabLayout = findViewById(R.id.TabLayout);
tabLayout.setupWithViewPager(viewPager);
Fragment fragmentHour=adapter.getItem(1);
onChangeDayListener2= (OnChangeDayListener) fragmentHour;
I am also have interface for send data from main activity in fragment:
public interface OnChangeDayListener{
void OnChange(WeatherList list,int pos);
}
but when i try to work with this callback in interface my recycler adapter always is null:
HourWeatherFragment:
public class HourWeatherFragment extends Fragment implements MainScreen.OnChangeDayListener{
private RecyclerView recyclerView;
private AdapterHour adapter;
private ArrayList<Weather> days;
Context context;
static HttpClient httpClient;
public HourWeatherFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
days=new ArrayList<>();
adapter = new AdapterHour(days,getActivity());
LinearLayoutManager LayoutManager = new LinearLayoutManager(getActivity().getBaseContext(),
LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(LayoutManager);
recyclerView.setAdapter(adapter);
days.add(new Weather());
recyclerView.getAdapter().notifyDataSetChanged();
Log.d("recycler","adapter seted!");
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_hour_weather, container, false);
recyclerView = rootView.findViewById(R.id.hour_list);
httpClient=new HttpClient();
MyAsyncTask task=new MyAsyncTask();
// task.execute("lviv");
return rootView;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context=context;
}
#Override
public void OnChange(WeatherList list,int pos) {
String date=list.getAverageWeather().get(pos).getDate();
ArrayList<Weather> weather=list.getByDate(date);
Log.d("ldata","size of weather for adding="+weather.size());
// days.add(new Weather());
if(adapter!=null){
adapter.notifyDataSetChanged();
Log.d("tag","first null!");}
else{
try{
recyclerView.getAdapter();}
catch (NullPointerException ex){
Log.d("tag","null!");//THERE ALWAYS NULL
}}
So,firstly creating activity,then i start load data and when data loaded i send data from MainActivity to HourWeatherFragment throught callback,
but when i receive data in fragment,my adapter is null,how i can fix it?
You can create a static singleton class to hold data and retrieve that data in the fragment.
public class DataHolder {
//create static variables here.
}
In your fragment simply retrieve the data and make it null after that.
Alternative solution
Another solution is to use Bundles. Follow the bundle solution here.
You must cast RecyclerView.
in your fragment and onCreateView method :
recyclerView = (RecyclerView) rootView.findViewById(R.id.hour_list);
I know this is an old question, but contrary to the accepted answer I think the issue is that the handle to the fragment's widget such as recyclerView is not available in the OnCreateView function.
The handles (or pointers if you wish) to the widgets are only guaranteed to exist in the OnViewCreated function.
This documentation has good description of the lifecycle of fragments:
https://guides.codepath.com/android/Creating-and-Using-Fragments
an extract is:
// This event is triggered soon after onCreateView().
// onViewCreated() is only called if the view returned from onCreateView() is non-null.
// Any view setup should occur here. E.g., view lookups and attaching view listeners.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ListView lv = (ListView) view.findViewById(R.id.lvSome);
lv.setAdapter(adapter);
}
Hope this helps.

PagerSlidingStrip is also loading another fragment

I have implemented Pager Sliding Strip and it is working totally fine.
I have 5 tabs each containing different fragment. When I click on 2nd tab to load respective fragment, it also load details of 3rd fragment, it showing the toast I coded in 3rd tab's fragment.
this is totally ruined the apps performance, How come I solve this problem I don't have any idea whats actually going on.
I am working on a really big project I cannot post the whole code.
Please Help me with this, I will post the respective code on demand.
Regards.
EDIT
Notification Fragment which is loading another fragment
ListView notification_listview;
ArrayList<FragmentNotificationDTO> arraylist;
NotificationAdapter adapter;
private static View notificationView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (notificationView != null) {
ViewGroup parent = (ViewGroup) notificationView.getParent();
if (parent != null)
parent.removeView(notificationView);
}
notificationView = inflater.inflate(R.layout.fragment_notification,
container, false);
initLayout(notificationView);
loadData();
return notificationView;
}
private void initLayout(View view) {
notification_listview = (ListView) view.findViewById(R.id.notification_listview);
arraylist = new ArrayList<FragmentNotificationDTO>();
adapter = new NotificationAdapter(mContext, arraylist);
notification_listview.setAdapter(adapter);
}
This is Food Fragment which is loaded also when we click on Notification Tab
private static View foodlistView;
RelativeLayout rl_foodshare, rl_foodrequested, rl_foodkitchen;
TextView tv_foodshare, tv_foodrequested, tv_foodkitchen;
ImageView img_foodshare, img_foodrequested, img_foodkitchen;
Fragment fr;
FragmentManager fm;
FragmentTransaction fragmentTransaction;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (foodlistView != null) {
ViewGroup parent = (ViewGroup) foodlistView.getParent();
if (parent != null)
parent.removeView(foodlistView);
}
foodlistView = inflater.inflate(R.layout.fragment_location_list,
container, false);
initLayout(foodlistView);
ChangeFragment(1);
return foodlistView;
}
MainActivity.java which contains the PagerSlidingStrip & View Pager
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()));
PagerSlidingTabStrip PGSTRIP = (PagerSlidingTabStrip) findViewById(R.id.tabs);
PGSTRIP.setViewPager(viewPager);
viewPager.setOffscreenPageLimit(0);
}
I solved my problem by overriding this method in each of my fragment and then calling the loading method when fragment's visibility is true to user.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// load data here
}else{
// fragment is no longer visible
}
}

Android memory leak issue when using ViewPagerAdapter with nested fragments

I have a fragment, fragment A, which holds a ViewPager. The ViewPager loads different fragments which the user can swipe through "indefinitely" (I use a really high number of pages/loops to emulate this). When a user clicks on the current ViewPager fragment, then fragment A with the ViewPager is replaced by fragment B in the fragment manager. When the user returns from fragment B, the backstack is popped using popBackStackImmediate(). If the user repeats this action several times, the heap begins to fill up by about 100kb at a time until the app starts to become sloppy and malfunction as the memory fills up. I'm unsure what exactly is causing this, can anyone help?
My fragment A with the ViewPager:
public class MainFragment extends Fragment {
private MainWearActivity mMainWearActivity;
View view;
private int currentPage;
private ViewPager pager;
private ViewPagerAdapter adapter;
private LinearLayout helpIcons;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainWearActivity = (MainWearActivity) getActivity();
adapter = new ViewPagerAdapter(this.getChildFragmentManager());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_main, container, false);
// Scrolling menu
pager = (ViewPager) view.findViewById(R.id.watchNavPager);
pager.setAdapter(adapter);
pager.addOnPageChangeListener(adapter);
// Set current item to the middle page
pager.setCurrentItem(Consts.FIRST_PAGE);
currentPage = Consts.FIRST_PAGE;
// Set number of pages
pager.setOffscreenPageLimit(4);
// Set no margin so other pages are hidden
pager.setPageMargin(0);
return view;
}
#Override
public void onDestroyView() {
pager = null;
super.onDestroyView();
}
}
My adapter class:
public class ViewPagerAdapter extends FragmentPagerAdapter implements
ViewPager.OnPageChangeListener {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position)
{
position = position % Consts.PAGES;
switch(position){
case Consts.AUDIO_POS:
return new AdapterAudioFragment();
case Consts.VOICE_POS:
return new AdapterVoiceFragment();
case Consts.MAIL_POS:
return new AdapterMailFragment();
case Consts.INFO_POS:
return new AdapterInfoFragment();
default:
return null;
}
}
#Override
public int getCount()
{
return Consts.PAGES * Consts.LOOPS; // (4 * 1000)
}
#Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {}
#Override
public void onPageSelected(int position) {}
#Override
public void onPageScrollStateChanged(int state) {}
}
One of my fragments that the adapter loads (they are all pretty much the same):
public class AdapterAudioFragment extends Fragment {
private ImageView menuImg;
private TextView menuText;
private LinearLayout rootView;
private MainWearActivity mMainWearActivity;
private View.OnClickListener imgClickListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainWearActivity = (MainWearActivity) getActivity();
imgClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
mMainWearActivity.replaceFragment(mMainWearActivity.getFragment(Consts.FRAG_AUDIO), Consts.FRAG_AUDIO);
}
};
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// Get root view of the fragment layout
rootView = (LinearLayout) inflater.inflate(
R.layout.fragment_nav_object, container, false);
// Set the current menu image and text
menuImg = (ImageView) rootView.findViewById(R.id.fragment_image);
menuImg.setImageResource(R.mipmap.ic_audio);
menuImg.setOnClickListener(imgClickListener);
menuText = (TextView) rootView.findViewById(R.id.menuTxt);
menuText.setText(Consts.MENU_HEADER_AUDIO);
// Set the current menu selection
mMainWearActivity.setCurrentSelection(Consts.AUDIO_POS);
return rootView;
}
}
I have a feeling that the adapter's fragments are all being created but never destroyed and piling up in the heap but I can't figure out how to resolve this. Do I need to call destroyItem in the adapter and manually destroy them? Any help would be most appreciated, thanks.
Adding this to Fragment stopped leaks for me:
#Override
public void onDestroyView() {
super.onDestroyView();
viewPager.setAdapter(null);
}
Looking at the source code, the problem seems to be that when calling ViewPager#setAdapter the view will register itself as observer for the adapter. So each time onViewCreated is called your pager adapter instance will have reference of the newly created view.
There is a specific PagerAdapter for your needs - FragmentStatePagerAdapter
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.

ListView in Fragment not refreshed

I created a tabbed app where the main acitvity contains two layouts. The top layout contains the actual tabbar (which is a fragment). Underneth the content layout contains another fragments depending on which tabbar button the user has clicked. In order to stay compatible with older android versions I use android.support.v4.app.Fragment.
So, in the tabbar menu I added two buttons and each button triggers another fragment in the content. This is what the code looks like:
public class TabbarMenuFragment extends Fragment implements View.OnClickListener {
LiveFragment liveFragment;
OddsFragment oddsFragment;
FragmentTransaction fragmentTransaction;
Button liveButton;
Button oddsButton;
public TabbarMenuFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
liveFragment = new LiveFragment();
oddsFragment = new OddsFragment();
fragmentTransaction = getFragmentManager().beginTransaction().add(R.id.content_view, oddsFragment);
fragmentTransaction.commit();
View rootView = (View) inflater.inflate(R.layout.tabbar_menu, container, false);
liveButton = (Button) rootView.findViewById(R.id.liveButton);
liveButton.setOnClickListener(this);
oddsButton = (Button) rootView.findViewById(R.id.oddsButton);
oddsButton.setOnClickListener(this);
return rootView;
}
public void updateUIInTabs() {
liveFragment.updateUI();
}
#Override
public void onClick(View v) {
if(v == liveButton) {
fragmentTransaction = getFragmentManager().beginTransaction().replace(R.id.content_view, liveFragment);
fragmentTransaction.commit();
}
if(v == oddsButton) {
fragmentTransaction = getFragmentManager().beginTransaction().replace(R.id.content_view, oddsFragment);
fragmentTransaction.commit();
}
updateUIInTabs();
}
}
The important thing is that the liveFragment is a Fragment that contains a ListView:
public class LiveFragment extends Fragment {
LiveMainAdapter adapter;
ListView list;
LayoutInflater inflater;
View rootView;
public LiveFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.inflater = inflater;
rootView = (View) inflater.inflate(R.layout.live_fragment, container, false);
adapter = new LiveMainAdapter(inflater);
list = (ListView) rootView.findViewById(R.id.live_fragment_ListView);
list.setAdapter(adapter);
list.setDivider(null);
list.setDividerHeight(0);
return rootView;
}
public void updateUI() {
if(list != null) {
list.invalidate();
adapter.createRowObjects();
adapter.notifyDataSetChanged();
}
}
}
The oddsFragment is so far just a dummy with a TextView:
public class OddsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = (View) inflater.inflate(R.layout.odds_fragment, container, false);
return rootView;
}
}
Now there are two settings which are important:
First:
As described above: I start the app and the oddsFragment is initally shown. Now, when I click on the liveFragment button the liveFragment's ListView is not updated.
Clicking again on the button for oddsFragment the oddsFragment is properly shown. Clicking back to liveFragment I get nothing - no ListView is shown.
The second setting:
Is exactly the same as the first, but instead I set the liveFragment as the intial view that is in TabbarMenuFragment I replace:
fragmentTransaction = getFragmentManager().beginTransaction().add(R.id.content_view, oddsFragment);
with
fragmentTransaction = getFragmentManager().beginTransaction().add(R.id.content_view, liveFragment);
Then the ListView is properly shown and the data in the list view is updated and displayed correctly. However, if I click on oddsFragement and then again on liveFragement the ListView has disappeared.
I already tried different things for over two hours now and I'm pretty desperated because I have not clue what might be the reason for this wired behaviour.
Anybody got an idea what is going on here?
Give this a try...
In your LiveFragment add a Handler and a Runnable and update the UI from your Runnable.
Handler handler = new Handler();
Runnable updater = new Runnable()
{
public void run()
{
if(list != null) {
list.invalidate();
adapter.createRowObjects();
adapter.notifyDataSetChanged();
}
}
};
and then change your updateUI() method in LiveFragment
public void updateUI()
{
handler.post(updater);
}

Random Out Of Bounds after removing item from static list used by multiple fragments

I have a fragment with a viewpager with adapter extending FragmentStatePagerAdapter with three slidable fragments inside. the main fragment has a static list of data, and three sub-fragments references and show the same list (don't ask why). The list item can be removed by a button inside the row layout or by clicking clear-all button after the list in each of those three fragments.
My problem is that after removing one or all the items with the buttons, sometimes i get an instant index out of bounds exception (no application code in stack trace, to find where the exception is coming from) or randomly sometimes removal work, but fragments nearby display old data with the extra item, and clicking to remove it ofcourse throws out of bounds exception, because after some debugging I can see that size of list passed to adapter to recreate the nearby fragment is lower by one (removal is successful) so I believe the list is not notified/invalidated correctly. Any help, since stacktrace can't help?
Btw I'm using FragmentStatePagerAdapter.POSITION_NONE to recreate the fragments with new data on each swipe, notifyDataSetChanged to notify the adapter of changed data, and invalidate() the listview in onViewCreated(), but they don't help.
relevant code:
Main Fragment
public class MainFragment extends BaseFragment<CategoryTreeItem> {
public static List<Map.Entry<EventTreeItem, String>> betList = new ArrayList<>();
...
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
mViewPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
SlidingTabLayout mSlidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setViewPager(mViewPager);
}
}
class MyPagerAdapter extends FragmentStatePagerAdapter {
private List<String> items;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
items = getResources().getStringArray(R.array.three_categories);
}
#Override
public Fragment getItem(int i) {
Fragment fragment;
switch (i) {
case 0:
fragment = new FirstFragment();
return fragment;
case 1:
fragment = new SecondFragment();
return fragment;
case 2:
fragment = new ThirdFragment();
return fragment;
default:
return null;
}
}
...
#Override
public int getItemPosition(Object object) {
return FragmentStatePagerAdapter.POSITION_NONE;
}
}
Three fragments (they are needed since the layout and functionality is a bit different)
public class First/Second/ThirdFragment extends BaseListFragment<ArrayList<EventTreeItem>> {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
MyListAdapter adapter = new MyListdapter(getActivity(), R.layout.item_first/second/thirdfragment, MainFragment.betList);
getListView().setItemsCanFocus(true);
View footerView = getLayoutInflater(savedInstanceState).inflate(R.layout.include_first/second/third_footer, getListView(), false);
getListView().addFooterView(footerView);
adapter.notifyDataSetChanged();
setListAdapter(adapter);
getListView().invalidate();
//handles REMOVE ALL button for all fragments footer button
Helper.setUpClearOption(footerView, adapter);
}
}
MyListAdapter
#CompileStatic
public class MyListAdapter extends ArrayAdapter<Map.Entry<EventTreeItem,String>> {
private int mResourceId;
private List<Map.Entry<EventTreeItem,String>> mObjects;
public MyListAdapter(Context context, int resource, List<Map.Entry<EventTreeItem,String>> objects) {
super(context, resource, objects);
mResourceId = resource;
mObjects = objects;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
view = LayoutInflater.from(getContext()).inflate(mResourceId, parent, false);
}
//------setting a lot of text for textViews
// .....
//------
ImageView ivRemove = (ImageView) view.findViewById(R.id.ivRemove);
ivRemove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Tried removing directly from adapter, not helping
// MyListAdapter.this.remove(mObjects.get(position));
MainFragment.betList.remove(position);
MyListAdapter.this.notifyDataSetChanged();
}
});
return view;
}
}
Remove All helper method (also returning instant OOB or not notifying neighbor fragments)
public static void setUpClearOption(View view, final ArrayAdapter adapter) {
ImageView ivRemoveAll = (ImageView) view.findViewById(R.id.ivRemoveAll);
ivRemoveAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
adapter.clear();
adapter.notifyDataSetChanged();
}
});
}
So any help is much appreciated!
I managed to fix My problem by creating three listadapters for each of my fragments (static adapters instantiaiting with null value ) and in onClick I check each of those three adapters if they are not null (since adapters are null until after onViewCreated, and it is called only when the current fragment is a neighbor). All three adapters use the same data.

Categories

Resources