synchronization of listviews inside view pager - android

Hi i got the viewpager :contains one fragment with two different views inside [A] and [B]. both views contain a list view. when I scroll , list view [A] and switch to second fragment I want list view [B] also be scrolled with the same amount. I've searched that I can set onTouchListener to the listview.please find below the code i used.
viewpager adapter
public class ViewPagerAdapter extends FragmentStatePagerAdapter implements
CurrencyScrollListener {
private String nBankName;
private List<Currency> list;
private String mycode;
private CurrencyViewPager[] mFragments = new CurrencyViewPager[2];
private int mCurrentScrollPosition;
#Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return super.getItemPosition(object);
}
public CurrencyViewPager getCurrencyFragment(int index) {
CurrencyViewPager pager = mFragments[index];
CurrencyViewPager other = mFragments[1-index];
if (pager == null) {
if (index == 0) {
pager = new CurrencyViewPager(list, nBankName, true, mycode,
this, 0);
} else {
pager = new CurrencyViewPager(list, nBankName, false, mycode,
this, 1);
}
mFragments[index] = pager;
}
if(other!=null && other.getCurrentPosition() != pager.getCurrentPosition()) {
pager.scrollTo( other.getCurrentPosition() );
}
return pager;
}
public ViewPagerAdapter(FragmentManager fm, List<Currency> currencyList,
String name, String code) {
super(fm);
this.list = currencyList;
this.nBankName = name;
this.mycode = code;
}
#Override
public Fragment getItem(int item) {
Log.i("ViewPagerAdapter","Currency Fragment #"+item);
return getCurrencyFragment(item);
}
#Override
public int getCount() {
return 2;
}
}
}
And single fragment containing list view
public class CurrencyViewPager extends BaseFragment {
private ListView mcurrencyListview;
private GeoCurrencyService mCurrency = GeoCurrencyService.getInstance();
ButtonPressListener buttonListener;
private CurrencyAdapter mCurrencyAdapter;
private String bankName;
private boolean checkFlag;
private ProgressBar mCurrencyProgress;
private TextView mCurrencyLoading;
private List<Currency> mList;
private String recCode;
private static int Firstposition;
private final CurrencyScrollListener listener;
private final int mListViewIndex;
// constructor
public CurrencyViewPager(List<Currency> myList, String name, boolean flag,String code, CurrencyScrollListener listener, int listViewIndex) {
super();
this.mList = myList;
this.bankName = name;
this.checkFlag = flag;
this.recCode = code;
this.listener = listener;
this.mListViewIndex = listViewIndex;
}
// interface
public interface ButtonPressListener {
public void onListItemPressed(Currency object, String name,String code);
}
// attach on listener
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
buttonListener = (ButtonPressListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement onButtonPressed");
}
}
// creating the main View.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.listbuy, container, false);
mcurrencyListview = (ListView) view.findViewById(R.id.BuyList);
mCurrencyAdapter = new CurrencyAdapter(getActivity(),
R.layout.currency_row, mList, checkFlag, getLanguage());
mcurrencyListview.setAdapter(mCurrencyAdapter);
// calling method getCurrency which take bank code as a parameter
/*getCurrency(code,null);*/
// reference to the list view of the corresponding layout
mcurrencyListview.setOnItemClickListener(new OnItemClickListener() {
// onClick on the List item
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
// getting Currency object according to the position
Currency currencyObject = mCurrencyAdapter.getItem(position);
// sending the object to the mainActivity
buttonListener.onListItemPressed(currencyObject, bankName,recCode);
}
});
return view;
}
}

First off, you should be using FragmentPagerAdapter instead of FragmentStatePagerAdapter (Look here for more information).
Now, to the question at hand.
Use the following to get the current position of ListView [A]
int index = mListA.getFirstVisiblePosition();
View v = mListA.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
And use this to set the position of ListView [B]:
mListB.setSelectionFromTop(index, top);
Look at this SO post for more information.

Related

How to update content in Fragment of ViewPager using AsyncTaskLoader?

I try to use AsyncTaskLoader in Fragment that is a child of ViewPager. Below a code of my DayFragment:
public class DayFragment extends Fragment
implements LoaderManager.LoaderCallbacks<DayAdapter.DayItem[]> {
private static final int CONTENT_LOADER = 0;
private DayAdapter mAdapter = null;
private int mWeekNumber = 1;
private int mDayCode = 1;
private Table.Timetable mTimetable;
private RecyclerView mRVContent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final MainActivity mainActivity = (MainActivity) getActivity();
View v = inflater.inflate(R.layout.content, container, false);
mRVContent = (RecyclerView) v.findViewById(R.id.rvContent);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mainActivity);
mRVContent.setLayoutManager(layoutManager);
mAdapter = new DayAdapter(getActivity());
mRVContent.setAdapter(mAdapter);
//Initialize the cursor loader
getLoaderManager().initLoader(CONTENT_LOADER, null, this).forceLoad();
return v;
}
#Override
public Loader<DayAdapter.DayItem[]> onCreateLoader(final int id, Bundle args) {
if(CONTENT_LOADER == id) {
return new ContentLoader(getContext(), mWeekNumber, mDayCode, mTimetable);
}
return null;
}
#Override
public void onLoadFinished(Loader loader, DayAdapter.DayItem[] items) {
if(CONTENT_LOADER == loader.getId()) {
mAdapter.setIs24HourFormat(SettingsManager.is24HourFormat(getContext()));
mAdapter.clear();
for (DayAdapter.DayItem item : items) {
mAdapter.add(item);
}
mAdapter.notifyDataSetChanged();
if (items.length == 0) {
mRVContent.setBackgroundResource(R.drawable.bg_lesson_empty);
} else {
mRVContent.setBackgroundColor(0xFFFFFFFF);
}
}
}
#Override
public void onLoaderReset(Loader loader) {
}
private static final class ContentLoader extends AsyncTaskLoader<DayAdapter.DayItem[]> {
private final int mWeekNumber;
private final int mDayCode;
private final Table.Timetable mTimetable;
public ContentLoader(Context context, final int weekNumber, final int dayCode,
Table.Timetable timetable) {
super(context);
mWeekNumber = weekNumber;
mDayCode = dayCode;
mTimetable = timetable;
}
#Override
public DayAdapter.DayItem[] loadInBackground() {
DatabaseHandler db = new DatabaseHandler(getContext());
db.openReadable();
List<Table.Lesson> lessons = db.findLessons(mDayCode, mWeekNumber, mTimetable.getId());
DayAdapter.DayItem[] items = new DayAdapter.DayItem[lessons.size()];
for (int i = 0; i < items.length; ++i) {
Table.Lesson lesson = lessons.get(i);
Table.Subject subject = db.getSubject(lesson.getSubjectId());
Table.Teacher teacher = db.getTeacher(lesson.getTeacherId());
if (teacher == null) {
teacher = new Table.Teacher(""); //Empty name
}
items[i] = new DayAdapter.DayItem()
.setId(lesson.getId())
.setTitle(subject.getTitle())
.setSubtitle(teacher.getName()));
}
db.close();
return items;
}
}
}
PageAdapater
public class PageAdapter extends FragmentStatePagerAdapter {
public static final int PAGE_COUNT = 7;
private int mWeekNumber;
private final int[] mDayCodes;
private final String[] mDays;
private final DayFragment[] mFragments = new DayFragment[7];
private Table.Timetable mTimetable;
private boolean mIsRebuildMode = false;
public PageAdapter(Context context, FragmentManager fm,
Table.Timetable timetable, final int weekNumber) {
super(fm);
//Initialize class members
}
#Override
public Fragment getItem(int position) {
DayFragment dayFragment;
if (mFragments[position] == null) {
dayFragment = new DayFragment();
Bundle args = new Bundle();
args.putSerializable(Keys.TIMETABLE, mTimetable);
dayFragment.setArguments(args);
dayFragment.setWeekNumber(mWeekNumber);
dayFragment.setDayCode(mDayCodes[position]);
mFragments[position]= dayFragment;
} else {
dayFragment = mFragments[position];
}
return dayFragment;
}
#Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
//do nothing here! no call to super.restoreState(arg0, arg1);
}
public void setWeekNumber(final int weekNumber) {
mWeekNumber = weekNumber;
Arrays.fill(mFragments, null);
}
public void setIsRebuildMode(final boolean isRebuildMode) {
mIsRebuildMode = isRebuildMode;
}
#Override
public CharSequence getPageTitle(final int position) {
return mDays[position];
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public int getItemPosition(Object object) {
if(mIsRebuildMode) {
return POSITION_NONE;
}
return super.getItemPosition(object);
}
}
But it doesn't call onLoadFinished method. I checked Log output... LoaderManager calls onCreateLoader but it never calls onLoadFinished except first run (when app started and ViewPager shows a first page (Fragment)). It's all! After if I switch a page to a next and a next and return to a first page LoaderManager doesn't call onLoadFinished for the first page too. But it creates loader calling onCreateLoader and resets loader calling onLoaderReset. Is it a joke from Google?
See fragment lifecycle. ViewPager don't re create fragment, just swipe them
-- Start ViewPager
: create
: createView
: start
: resume
not changed if you swipe fragments
--- sleep smartphone
: pause
: stop
--- wakeup smartphone
: start
: resume
: pause
--- Close ViewPager
: stop
: detach

Updating ViewPager Adapter?

I am using tabLayout which is attached with the viewPager. I have implemented viewPager Adapter using FragmentStatePager adapter, because the tabLayout list is big.
ViewPager creates a new instance of each fragment, and inside the fragment, i am using recyclerView to the data.
Now, before initiating the viewPager i am making a call to the server, and in success response, i am initiating viewPager for the first time. Then viewPager calls its getItem() callback, where it gets the data for the first position initialises the fragment and it's recyclerView.
It also call getItem() for the next position as i have set the offScreenLimit() to 2, which is fine and working well.
The problem is when it calls getItem() and creates the fragment, at that time, i am checking if i have the data, if not, then i am making a callback to get data from server.
And if user visits that position, i want to updated the fragment recyclerView.
Here, i have passed the reference of the main object in the fragment, so on success of request, it updates the main object, and the updated object will be present inside the fragment list.
Since, it's an asynchronous call, i want to show a loader and then update the fragment.
Here is where my problem lies. I am not able to update the fragment recyclerView. It's updating but taking time.
I had tried using return POSITION_NONE which worked fine, but it's not a good approach as it creates a new fragment every time.
This is my viewPagerAdapter.
public class ShowTimeViewPageAdapter extends FragmentStatePagerAdapter {
private static final String TAG = ShowTimeViewPageAdapter.class.getSimpleName();
private Context mContext;
private List<String> mDateStringList;
private FragmentManager fragmentManager;
private IShowTimeActivity mIShowTimeActivity;
private List<String> mDateCodes;
private LinkedHashMap<String, List<Venue>> mVenueHashMap;
public ShowTimeViewPageAdapter(FragmentManager fm, Context context, IShowTimeActivity showTimeActivity, List<String> createdDates, List<String> dateCodes, LinkedHashMap<String, List<Venue>> venueHashMap) {
super(fm);
this.mContext = context;
this.mIShowTimeActivity = showTimeActivity;
this.fragmentManager = fm;
this.mDateCodes = dateCodes;
this.mVenueHashMap = venueHashMap;
this.mDateStringList = createdDates;
}
private String getDateCode(int pos) {
String dateCode = null;
try {
dateCode = mDateCodes.get(pos);
} catch (IndexOutOfBoundsException e) {
Logger.d(TAG, "Index out of bound");
}
return dateCode;
}
private List<Venue> getVenuesList(String dateCode) {
return mVenueHashMap.get(dateCode);
}
#Override
public Fragment getItem(int position) {
if (getDateCode(position) != null) {
if (getVenuesList(getDateCode(position)) == null) {
if(position!=0){
mIShowTimeActivity.requestForTheVenueListByDateCode(getDateCode(position), position);
}
}
}
ShowTimeFragment showTimeFragment = ShowTimeFragment.newInstance(mDateStringList.get(position).split(";")[2]);
fragmentManager.beginTransaction().add(showTimeFragment,""+position);
return showTimeFragment;
}
#Override
public int getCount() {
return mDateStringList.size();
}
public View getTabView(int position) {
String[] dateStr = mDateStringList.get(position).split(";");
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View tabView = layoutInflater.inflate(R.layout.show_time_tab_layout, null, false);
TextViewRoboto day = (TextViewRoboto) tabView.findViewById(R.id.show_time_tab_day);
TextViewRoboto date = (TextViewRoboto) tabView.findViewById(R.id.show_time_tab_date);
day.setText(dateStr[0]);
date.setText(dateStr[1]);
return tabView;
}
}
And this is the Fragment.
public class ShowTimeFragment extends Fragment {
#Bind(R.id.show_time_fragment_recycler_view) RecyclerView mShowTimeRecyclerView;
#Bind(R.id.show_time_fragment_no_data_text_view) TextViewRoboto mShowTimeNoDataTextView;
private static LinkedHashMap<String, List<Venue>> mVenueList = ShowTimeActivity.mVenueHashMap;
private ShowTimeRecyclerViewAdapter mShowTimeRecyclerViewAdapter;
private static final String KEY_CODE = "date_key";
public ShowTimeFragment() {
}
public static ShowTimeFragment newInstance(String dateCode) {
Bundle bundle = new Bundle();
bundle.putString(KEY_CODE, dateCode);
ShowTimeFragment showTimeFragment = new ShowTimeFragment();
showTimeFragment.setArguments(bundle);
return showTimeFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.show_time_fragment, container, false);
ButterKnife.bind(this, view);
String code = getArguments().getString(KEY_CODE);
List<Venue> venueList = mVenueList.get(code);
if (venueList != null && venueList.size() > 0) {
mShowTimeRecyclerView.setVisibility(View.VISIBLE);
mShowTimeNoDataTextView.setVisibility(View.GONE);
mShowTimeRecyclerViewAdapter = new ShowTimeRecyclerViewAdapter(venueList, getContext());
mShowTimeRecyclerView.setAdapter(mShowTimeRecyclerViewAdapter);
CustomLinearLayoutManager cl = new CustomLinearLayoutManager(getActivity(), 1, false);
mShowTimeRecyclerView.setLayoutManager(cl);
RecyclerView.OnItemTouchListener disabler = new RecyclerViewDisabler();
mShowTimeRecyclerView.addOnItemTouchListener(disabler); // disables scrolling
} else {
mShowTimeNoDataTextView.setVisibility(View.VISIBLE);
mShowTimeRecyclerView.setVisibility(View.GONE);
mShowTimeNoDataTextView.setText("NO Data Available");
}
return view;
}
public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
return true;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
protected void addFragment(int containerViewId, Fragment fragment, String fragmentTag) {
getActivity().getSupportFragmentManager().beginTransaction().add(containerViewId, fragment, fragmentTag).disallowAddToBackStack().commit();
}
public void onDestroyView() {
super.onDestroyView();
}
}
In the above fragment
private static LinkedHashMap<String, List<Venue>> mVenueList = ShowTimeActivity.mVenueHashMap;
this hashMap is the reference to the original hashMap, which is updated on each request.
Any kind of help or suggestions would be appreciated.

How to update fragment's data used in ViewPager? View is not showing the updated data

I know the same question has been asked so many times but I am not able to solve my issue.
I have created an Activity which has a ViewPager which should have 4 Pages.
I am using the same Fragment for all pages. The Fragment has a GridView which should be updated whenever I swipe to the other page.
Following are the classes & XML layouts I have used to create it.
Activity layout activity_discover.xml
<android.support.v4.view.ViewPager
android:id="#+id/activity_discover_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip" >
<android.support.v4.view.PagerTabStrip
android:id="#+id/activity_discover_pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:textColor="#color/black"
android:textSize="#dimen/header_text" />
</android.support.v4.view.ViewPager>
</RelativeLayout>
Activity DiscoverActivity.java
public class DiscoverActivity extends FragmentActivity implements OnClickListener, OnPageChangeListener
{
private final static String TAG = "DiscoverActivity";
private UtilDialog utilDialog;
MPagerAdapter adapterViewPager;
PagerTabStrip pagerTabStrip;
ViewPager viewPager;
public ArrayList<String> listCategory;
LMProgressDialog progressDialog;
private RelativeLayout relativeCountry;
private RelativeLayout relativeCity;
private TextView tvCountry;
private TextView tvCity;
private String selectedCategory;
private int selectedCityID = 0;
private int selectedCategoryID = 0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discover);
initParameters();
initView();
}
void initParameters()
{
progressDialog = new LMProgressDialog(this);
utilDialog = new UtilDialog(this);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
editor = preferences.edit();
editor.commit();
selectedCategory = getResources().getString(R.string.adventure);
listCategory = new ArrayList<String>();
listCategory.add(getResources().getString(R.string.adventure));
listCategory.add(getResources().getString(R.string.night_life));
listCategory.add(getResources().getString(R.string.life_styles));
listCategory.add(getResources().getString(R.string.events));
}
void initView()
{
viewPager = (ViewPager) findViewById(R.id.activity_discover_view_pager);
viewPager.setOnPageChangeListener(this);
adapterViewPager = new MPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapterViewPager);
pagerTabStrip = (PagerTabStrip) findViewById(R.id.activity_discover_pager_tab_strip);
pagerTabStrip.setTabIndicatorColor(getResources().getColor(R.color.white));
}
#Override
protected void onDestroy()
{
super.onDestroy();
}
public class MPagerAdapter extends FragmentPagerAdapter
{
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;
public MPagerAdapter(FragmentManager fm)
{
super(fm);
mFragmentManager = fm;
mFragmentTags = new HashMap<Integer, String>();
}
#Override
public int getCount()
{
return 4;
}
#Override
public Fragment getItem(int position)
{
Fragment fragment = Fragment.instantiate(DiscoverActivity.this,
FragmentMediaContent.class.getName(), null);
return fragment;
}
#Override
public Object instantiateItem(ViewGroup container, int position)
{
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment)
{
// record the fragment tag here.
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
}
return obj;
}
public Fragment getFragment(int position)
{
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return mFragmentManager.findFragmentByTag(tag);
}
#Override
public CharSequence getPageTitle(int position)
{
return listCategory.get(position).toString().toUpperCase();
}
}
#Override
public void onPageScrollStateChanged(int arg0)
{
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
#Override
public void onPageSelected(int position)
{
selectedCategoryID = position;
selectedCategory = listCategory.get(position);
try
{
JSONObject jsonObject = new JSONObject();
jsonObject.put(Constants.CITY_ID, selectedCityID);
jsonObject.put(Constants.CATEGORY, selectedCategory);
makeJsonObjectRequest(Request.Method.POST, jsonObject, API.URL_LOAD_MEDIA);
} catch (JSONException e)
{
e.printStackTrace();
}
}
void prepareMediaList(JSONArray arrayMedia)
{
int noOfMedia = arrayMedia.length();
ArrayList<MediaType> listMedia = new ArrayList<MediaType>();
for (int i = 0; i < noOfMedia; i++)
{
try
{
JSONObject objectMedia = arrayMedia.getJSONObject(i);
int id = objectMedia.getInt(Constants.ID);
String category = objectMedia.getString(Constants.CATEGORY);
String mediaType = objectMedia.getString(Constants.MEDIA_TYPE);
int cityID = objectMedia.getInt(Constants.CITIES_ID);
String path = objectMedia.getString(Constants.PATH);
String thumbnailPath = objectMedia.getString(Constants.THUMBNAIL_PATH);
String description = objectMedia.getString(Constants.DESCRIPTION);
int userID = objectMedia.getInt(Constants.USERS_ID);
listMedia.add(new MediaType(id, mediaType, path, category, userID, cityID, 0, description, thumbnailPath));
} catch (JSONException e)
{
e.printStackTrace();
}
}
FragmentMediaContent fragment = (FragmentMediaContent) adapterViewPager.getFragment(selectedCategoryID);
Log.i(TAG, "fragment: " + fragment);
fragment.updateData(listMedia, selectedCategory);
}
}
Fragment class FragmentMediaContent.java:
public class FragmentMediaContent extends Fragment
{
private final static String TAG = "FragmentMediaContent";
public static final String FRAGMENT_POSITION = null;
private GridView gridView;
private UtilDialog utilDialog;
private SharedPreferences preferences;
private Editor editor;
private ArrayList<MediaType> listMedia;
MediaAdapter mediaAdapter;
private int cityID;
private String category;
LMProgressDialog progressDialog;
TextView tvTest;
public static FragmentMediaContent newInstance(int num)
{
FragmentMediaContent f = new FragmentMediaContent();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_media_content, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
initParameters();
initViews();
}
void initParameters()
{
getSize();
listMedia = new ArrayList<MediaType>();
utilDialog = new UtilDialog(getActivity());
progressDialog = new LMProgressDialog(getActivity());
preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
editor = preferences.edit();
mediaAdapter = new MediaAdapter(getActivity(), listMedia);
}
void initViews()
{
tvTest = (TextView) getActivity().findViewById(R.id.fragment_media_content_tv_test);
tvTest.setText(category+" no of media");
tvTest.setVisibility(View.GONE);
gridView = (GridView) getActivity().findViewById(R.id.fragment_media_content_grid_view);
gridView.setAdapter(mediaAdapter);
}
/**
* MediaAdapter : ArrayAdapter class which prepares view for list of
* MediaType.
*
*/
class MediaAdapter extends ArrayAdapter<MediaType>
{
MediaAdapter(Context context, ArrayList<MediaType> list)
{
super(context, R.layout.cell_media_view, R.id.cell_media_view_tv_test, list);
}
public View getView(int position, View convertView, ViewGroup parent)
{
View row = super.getView(position, convertView, parent);
MediaViewHolder holder = (MediaViewHolder) row.getTag();
if (holder == null)
{
holder = new MediaViewHolder(row);
row.setTag(holder);
}
final MediaType mediaType = getMedia(position, this);
String thumbnailPath = mediaType.getThumbnailPath();
String path = mediaType.getPath();
String type = mediaType.getMediaType();
// imageLoader.get(type.equals(Constants.TYPE_IMAGE) ? path :
// thumbnailPath, ImageLoader.getImageListener(holder.ivMedia,
// R.drawable.logo, R.drawable.ic_launcher));
holder.ivType.setVisibility(type.equals(Constants.TYPE_IMAGE) ? View.GONE : View.VISIBLE);
holder.ivMedia.setLayoutParams(new FrameLayout.LayoutParams(THUMBNAIL_SIZE, THUMBNAIL_SIZE));
Picasso.with(getActivity()).load(type.equals(Constants.TYPE_IMAGE) ? path : thumbnailPath).noFade().centerCrop().resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE).placeholder(R.drawable.loading)
.error(R.drawable.no_image).into(holder.ivMedia);
return row;
}
}
public void updateData(ArrayList<MediaType> listMedia, String category)
{
Log.i(TAG, "Updating data for: " + category);
Log.i(TAG, "No of media items: " + listMedia.size());
// this.listMedia.clear();
// this.listMedia.addAll(listMedia);
// mediaAdapter.notifyDataSetChanged();
mediaAdapter = new MediaAdapter(getActivity(), listMedia);
gridView.setAdapter(mediaAdapter);
tvTest.setText(category + ", No of Media : " + listMedia.size());
}
int THUMBNAIL_SIZE = 200;
/**
* #param position
* #return MediaType object from specified position
*/
private MediaType getMedia(int position, MediaAdapter mediaAdapter)
{
return (MediaType) mediaAdapter.getItem(position);
}
}
Fragment fragment_media_content.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blue"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/fragment_media_content_tv_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/white" />
<GridView
android:id="#+id/fragment_media_content_grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:horizontalSpacing="5dip"
android:numColumns="3"
android:verticalSpacing="5dip" />
</LinearLayout>
On page swipe (or it could be any other event) I hit an API which gives me some data that I have to update in the corresponding Fragment.
Whenever I get the data from server I call the prepareMediaList method which calls the updateData method of Fragment. I can see in logs that there is data in list but that data is not shown in the Fragment's GridView (not even in TextView).
I am really not getting what is wrong in this.
Now it has become very frustrating, looks so simple but still couldn't find any solution.
Edit
I just tried with one Fragment only & it is working properly. So there is something which has to do with multiples.
Edit 2
I couldn't find the solution for this so I had to switch to alternate way. I removed the Fragments from ViewPager instead I added static views to it. In my case I added four GridViews to ViewPager. This was simple & bit complex but most important thing is, it is working the way I wanted.
But still I am looking for the answer.
After checking your code more in details i see you do not require to re-initliaze your MediaAdapter inside updateData method.
You simply require to update your updateData as
listMedia.clear();
this.listMedia.addAll(listMedia);
mediaAdapter.notifyDatasetChanged();
This will reload your data in gridview. Change i suggested will refresh the data in your arraylist which is being used for rendering gridview and then you notify your mediaAdapter to reload the list.

listview synchronization when switching between fragments in a viewpager

I have view pager in my app. inside a viewpager there are two fragments [1] and [2] both with list view inside [A] and [B]. when I scroll listview [A] and switch fragment [2] I want listview [B] to be scrolled with the same amount automatically. please help
here is my snippet
public class CurrencyViewPager extends BaseFragment {
private ListView mcurrencyListview;
private GeoCurrencyService mCurrency = GeoCurrencyService.getInstance();
ButtonPressListener buttonListener;
private CurrencyAdapter mCurrencyAdapter;
private String bankName;
private boolean checkFlag;
private ProgressBar mCurrencyProgress;
private TextView mCurrencyLoading;
private List<Currency> mList;
private String recCode;
private static int Firstposition;
private final CurrencyScrollListener listener;
private final int mListViewIndex;
// constructor
public CurrencyViewPager(List<Currency> myList, String name, boolean flag,String code, CurrencyScrollListener listener, int listViewIndex) {
super();
this.mList = myList;
this.bankName = name;
this.checkFlag = flag;
this.recCode = code;
this.listener = listener;
this.mListViewIndex = listViewIndex;
}
// interface
public interface ButtonPressListener {
public void onListItemPressed(Currency object, String name,String code);
}
// attach on listener
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
buttonListener = (ButtonPressListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement onButtonPressed");
}
}
// creating the main View.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i("TAG","onCreateView");
View view = inflater.inflate(R.layout.listbuy, container, false);
mcurrencyListview = (ListView) view.findViewById(R.id.BuyList);
mCurrencyAdapter = new CurrencyAdapter(getActivity(),
R.layout.currency_row, mList, checkFlag, getLanguage());
mcurrencyListview.setAdapter(mCurrencyAdapter);
mcurrencyListview.setSelection(Firstposition);
// calling method getCurrency which take bank code as a parameter
/*getCurrency(code,null);*/
// reference to the list view of the corresponding layout
mcurrencyListview.setOnItemClickListener(new OnItemClickListener() {
// onClick on the List item
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
// getting Currency object according to the position
Currency currencyObject = mCurrencyAdapter.getItem(position);
// sending the object to the mainActivity
buttonListener.onListItemPressed(currencyObject, bankName,recCode);
}
});
return view;
}
// method getCurrency which takes bank code as a parameter and
// sets the adapter to the list on onPostExecute.
}
and fragment adapter for viewpager
public class ViewPagerAdapter extends FragmentStatePagerAdapter implements
CurrencyScrollListener {
private String nBankName;
private List<Currency> list;
private String mycode;
private CurrencyViewPager[] mFragments = new CurrencyViewPager[2];
private int mCurrentScrollPosition;
#Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return super.getItemPosition(object);
}
public CurrencyViewPager getFCurrencyFragment(int index) {
CurrencyViewPager pager = mFragments[index];
if (pager == null) {
if (index == 0) {
pager = new CurrencyViewPager(list, nBankName, true, mycode,
this, 0);
} else {
pager = new CurrencyViewPager(list, nBankName, false, mycode,
this, 1);
}
mFragments[index] = pager;
}
return pager;
}
public ViewPagerAdapter(FragmentManager fm, List<Currency> currencyList,
String name, String code) {
super(fm);
this.list = currencyList;
this.nBankName = name;
this.mycode = code;
}
#Override
public Fragment getItem(int item) {
Log.i("TAG","getItem");
return getFCurrencyFragment(item);
}
#Override
public int getCount() {
return 2;
}
}

ViewPager is trying to recreate a Fragment from bad data

The main problem I am running into is that when I try to update my PagerAdapter with a brand new set of data, I get a FC. More specifically, I get the FC only if I remove something from the PagerAdapter's dataset.
In my Main activity I have this loader callback:
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor newCursor) {
List<CycleItem> cycleItems = CursorInflator.inflateList(newCursor, CycleItem.class);
mCycleAdapter.setCycleList(cycleItems);
mIndicator.notifyDataSetChanged();
}
Here is my CycleViewPagerAdapter (mCycleAdapter is a reference to this):
public class CycleViewPagerAdapter extends FragmentPagerAdapter implements TitleProvider {
private ArrayList<CycleItem> mCycleItems;
private CyclePagerCallbacks mParent;
public CycleViewPagerAdapter(CyclePagerCallbacks parent, FragmentManager fm) {
super(fm);
mParent = parent;
mCycleItems = new ArrayList<CycleItem>();
}
public CycleViewPagerAdapter(FragmentManager fm, List<CycleItem> cycleItems) {
super(fm);
mCycleItems = (ArrayList<CycleItem>) cycleItems;
}
public void setCycleList(List<CycleItem> cycleItems) {
mCycleItems = (ArrayList<CycleItem>) cycleItems;
notifyDataSetChanged();
}
#Override
public Fragment getItem(int position) {
return CycleDetailFragment.newInstance(mParent, mCycleItems.get(position % mCycleItems.size()).getId());
}
public String getTitle(int position) {
return mCycleItems.get(position % mCycleItems.size()).getName();
}
#Override
public int getCount() {
if (mCycleItems != null) {
return mCycleItems.size();
} else {
return 0;
}
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
This CycleViewPagerAdapter creates and returns CycleDetailFragments when the getItem method is called. Here is that class:
public class CycleDetailFragment extends Fragment implements PaginatedFragmentProtocol {
public interface CyclePagerCallbacks {
public void removeCycle(Uri cycleUri);
}
private static final String TAG = "CycleDetailFragment";
private CyclePagerCallbacks mParent;
private long mCycleId;
private Cycle cycle;
private static final String CYCLE_ID_KEY = "cycle_id";
private TextView mCycleName;
private TextView mNumItem;
private Button mDeleteCycle;
public static CycleDetailFragment newInstance(CyclePagerCallbacks parent, long cycleId) {
CycleDetailFragment cycleDetailFragment = new CycleDetailFragment(parent);
Bundle bundle = new Bundle();
bundle.putLong(CYCLE_ID_KEY, cycleId);
cycleDetailFragment.setArguments(bundle);
return cycleDetailFragment;
}
public CycleDetailFragment(CyclePagerCallbacks parent) {
mParent = parent;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle arguments = getArguments();
if (arguments != null) {
mCycleId = arguments.getLong(CYCLE_ID_KEY);
} else {
mCycleId = 0;
}
Log.i(TAG, Long.toString(mCycleId));
final Uri cycleUri = ContentUris.withAppendedId(CycleContentProvider.CONTENT_URI, mCycleId);
Cursor cursor = getActivity().getContentResolver().query(cycleUri, null, null, null, null);
final Cycle cycle = CursorInflator.inflateOne(cursor, Cycle.class);
Uri cycleItemsUri = ContentUris.withAppendedId(CycleItemContentProvider.CYCLE_ID_FIELD_CONTENT_URI, mCycleId);
Cursor cycleItemsCursor = getActivity().getContentResolver().query(cycleItemsUri, null, null, null, null);
mCycleName.setText(cycle.getName() + " " + cycle.getId());
mNumItem.setText(Integer.toString(cycleItemsCursor.getCount()));
mDeleteCycle.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getContentResolver().delete(cycleUri, null, null);
mParent.refresh();
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i("Creating View", "Cycle ID: " + mCycleId);
View view = inflater.inflate(R.layout.cycle_detail, container, false);
mCycleName = (TextView) view.findViewById(R.id.cycle_name);
mNumItem = (TextView) view.findViewById(R.id.num_items);
mDeleteCycle = (Button) view.findViewById(R.id.delete_cycle);
return view;
}
#Override
public String getFragmentTitle() {
return cycle.getName();
}
}
So you see that the CycleDetailFragment looks in the database for information to populate the view.
Here is the problem I am having. After I DELETE a Cycle from the database, the onLoadFinished method is called and the cycleItems is populated with the correct items, but once mCycleAdapter.setCycleList(cycleItems) is called after this deletion I get my error. The onAcitivityCreated method in the CycleDetailFragment is called (not by me or my PagerAdapter - something else internal), but it is fed data that should no longer exist! The bundle that it is passed contains the cycleId of the item that I just deleted and that does not exist in the freshly pulled cycleItems list that I just created. So, it tries to pull something from the database that no longer exists and null pointer exceptions are thrown.
How can I refresh the dataset of my PagerAdapter without the ViewPager trying to use old data first?
shouldn't you use FragmentStatePagerAdapter here?

Categories

Resources