Reputation: 439
I have fragment view pager in activity, that creates a number of pages of entered number before. In each fragment, i have recycler view that needs to update each time user moves to the relevant page. on resume() of each fragment I have getter of data from main activity.
What I am experiencing is while I'm going to next page first time it's not updated, but if after some page movements I would back to it, it is updated, with same resume() code.
I tried some delays after updating the data, it didn't help.
So if before updating data I would check every page it would work as I planned, but if the page was not created before (due to pager adapter) but I still use the same code for updating, it does not work.
I would be glad for some help, stacked on it for 2 days already.
Main Activity:
package com.slavafleer.tipcalculator02;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import com.slavafleer.tipcalculator02.recycler.PageHeaderAdapter;
import java.util.ArrayList;
public class ManualModeActivity extends AppCompatActivity implements
PageHeaderAdapter.Callbacks, DinerFragment.Callbacks {
private int mDinersAmount;
private ViewPager mViewPagerDiners;
private PageHeaderAdapter mHeaderAdapter;
private DinersPagerAdapter mDinersPagerAdapter;
private ArrayList<Order> mOrders;
public ArrayList<Order> getOrders() {
return mOrders;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manual_mode);
mOrders = new ArrayList<>();
// Get diners amount from previous activity
Intent intent = getIntent();
mDinersAmount = intent.getIntExtra(Constants.KEY_DINNERS_AMOUNT, 1);
// Initialise PageHeader Recycler
mHeaderAdapter = new PageHeaderAdapter(this, mDinersAmount, this);
final RecyclerView recyclerPageHeader = (RecyclerView) findViewById(R.id.recyclerViewPagerHeader);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerPageHeader.setLayoutManager(linearLayoutManager);
recyclerPageHeader.setAdapter(mHeaderAdapter);
// Initialise ViewPager
mViewPagerDiners = (ViewPager) findViewById(R.id.viewPagerDiners);
FragmentManager fragmentManager = getSupportFragmentManager();
mDinersPagerAdapter = new DinersPagerAdapter(fragmentManager, mDinersAmount);
mViewPagerDiners.setAdapter(mDinersPagerAdapter);
// ViewPager Listener - synchronise with headers recycler
mViewPagerDiners.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
// Gets position for selected page
@Override
public void onPageSelected(int position) {
mHeaderAdapter.selectItem(position);
linearLayoutManager.smoothScrollToPosition(recyclerPageHeader, null,position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
// HeaderPage Adapter Callbacks
// Scroll ViewPager by clicked Header
@Override
public void onItemClick(int position) {
mViewPagerDiners.setCurrentItem(position, true);
}
// DinerFragment.OrderDialog.Callbacks
// Send data to PagerAdapter that would sent to each fragment
@Override
public void onDialogAddClick(Order order) {
Log.d("test", "onDialogAddClick");
mOrders.add(order);
mDinersPagerAdapter.updateOrders();
}
}
PagerAdapter
package com.slavafleer.tipcalculator02;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.ArrayList;
/**
* PagerAdapter for ManualModeActivity ViewPager
*/
public class DinersPagerAdapter extends FragmentPagerAdapter {
private int mDinersAmount;
private ArrayList<DinerFragment> mDinerFragments;
public DinersPagerAdapter(FragmentManager fm, int dinersAmount) {
super(fm);
mDinersAmount = dinersAmount;
mDinerFragments = new ArrayList<>();
}
@Override
public Fragment getItem(int position) {
// Insert diners amount to fragment
Bundle bundle = new Bundle();
bundle.putInt(Constants.KEY_DINNERS_AMOUNT, mDinersAmount);
bundle.putInt(Constants.KEY_CURRENT_PAGE, position);
DinerFragment dinerFragment = new DinerFragment();
dinerFragment.setArguments(bundle);
mDinerFragments.add(dinerFragment); // save fragments references
return dinerFragment;
}
// Diners amount + All
@Override
public int getCount() {
return mDinersAmount + 1;
}
// Update order list in each fragment of view pager
public void updateOrders() {
for(DinerFragment dinerFragment : mDinerFragments) {
dinerFragment.onResume();
}
}
}
Fragment
package com.slavafleer.tipcalculator02;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.slavafleer.tipcalculator02.recycler.OrdersAdapter;
import java.util.ArrayList;
/**
* Diner Fragment Class
*/
public class DinerFragment extends Fragment implements OrderDialog.Callbacks {
private ArrayList<Order> mOrders = new ArrayList<>();
private RecyclerView mRecyclerViewOrders;
private ImageView mImageViewAddOrderButton;
private int mDinersAmount;
private OrdersAdapter mOrdersAdapter;
private int mDinerId;
private Callbacks mCallbacks;
public DinerFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("test", "onCreateView");
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_diner, container, false);
mCallbacks = (Callbacks) inflater.getContext();
// Get Diners Amount
final Bundle bundle = getArguments();
if(bundle != null) {
mDinersAmount = bundle.getInt(Constants.KEY_DINNERS_AMOUNT);
mDinerId = bundle.getInt(Constants.KEY_CURRENT_PAGE);
Log.d("test", "onCreateView " + mDinerId);
}
mRecyclerViewOrders = (RecyclerView) view.findViewById(R.id.recyclerViewOrders);
mOrdersAdapter = new OrdersAdapter(getActivity(), mOrders);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerViewOrders.setLayoutManager(linearLayoutManager);
mRecyclerViewOrders.setAdapter(mOrdersAdapter);
// Due to the bug, we could use just listener and not OnClick in Fragment
mImageViewAddOrderButton = (ImageView) view.findViewById(R.id.imageViewAddButton);
mImageViewAddOrderButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ArrayList<Integer> currentPage = new ArrayList<>();
currentPage.add(mDinerId);
OrderDialog orderDialog = new OrderDialog(getActivity(),
mDinersAmount, currentPage, DinerFragment.this);
orderDialog.show();
}
});
return view;
}
@Override
public void onResume() {
super.onResume();
Log.d("test", "onResume " + mDinerId);
ManualModeActivity activity = (ManualModeActivity) getActivity();
mOrders = activity.getOrders();
for(Order order : mOrders) {
Log.d("test", order.getPrice() + "");
}
int size = mOrders.size();
mOrdersAdapter.notifyDataSetChanged();
mRecyclerViewOrders.smoothScrollToPosition(size);
}
// Blank OrderDialog.Callbacks
// used due to Implements for creation OrderDialog
@Override
public void onDialogAddClick(Order order) {
mCallbacks.onDialogAddClick(order);
}
public interface Callbacks {
void onDialogAddClick(Order order);
}
}
Upvotes: 0
Views: 1658
Reputation: 381
ViewPager adapter creates 2 fragments at the same time. for instance when you're on page 0, it also creates page 1(lifecycle for page 1: OnCreate->OnCreateView->OnResume->OnPause->OnResume).When you swipe to page 1 only method that is being called is SetMenuVisibility. So in order to update data for page 1 is to call setMenuVisibilty inside of Fragment:
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if(menuVisible && isResumed()){
settingAdapter();
}
}
So here inside of settingAdapter i reloaded data. so far,it's the best trick i made toward fragments with recyclerviews inside viewpager. But still there are few milliseconds delay for populating fragment with new data))) I hope this will help you
Upvotes: 0
Reputation: 439
Finally what I did is replacing mOrdersAdapter.notifyDataSetChanged() on recreating the adapter. I understand that is not a very smart solution but visually it does work as I needed.
I would not mark it as answer cause I still want to know why it acts like I wrote before.
Thanks again.
// mOrdersAdapter.notifyDataSetChanged();
mOrdersAdapter = new OrdersAdapter(getActivity(), mOrders);
mRecyclerViewOrders.setAdapter(mOrdersAdapter);
Upvotes: 0
Reputation: 389
Instead of using onResume use the onPageSelected method and used the passed fragment for context to call the updating method in the fragment.
Upvotes: 1