FragmentStatePager instantiate my Fragment twice - android-fragments

I am using the following the custom viewPager with FragmentStatePagerAdapter to create a set of fragments for user to write the specific profile. The data of the user can be retrieved by SQL with respect to the position of the child page of the viewpager. When it comes to the execution , I see that the fragment is created twice whenever the first time to be load and swipe to the other uncached pages . I have found the referenceFragment Hash map to retrieve the current fragment to be load once only instead of two fragments to be loaded. COuld you please tell me the better way to load the fragment once only ?
The below is my working :
static SectionsPagerAdapter mSectionsPagerAdapter;
static CustomViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSectionsPagerAdapter = new SectionsPagerAdapter(fm);
dotsCount = mSectionsPagerAdapter.getCount();
dots = new ImageView[dotsCount];
dots[0] = dot1;
dots[1] = dot2;
dots[2] = dot3;
dots[3] = dot4;
dots[4] = dot5;
dots[5] = dot6;
dots[6] = dot7;
setUiPageViewController();
isTablet= ReadExcel.isTabletDevice(this);
mViewPager = (CustomViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setEnabled(true);
mViewPager.setOffscreenPageLimit(0);
mViewPager.setOnPageChangeListener(viewPagerPageChangeListener);
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public static PlaceholderFragment newInstance(int sectionNumber) {
// PlaceholderFragment fragment = new PlaceholderFragment();
PlaceholderFragment fragment = ((SectionsPagerAdapter)mViewPager.getAdapter()).getFragment(sectionNumber);
if(fragment==null){
fragment = new PlaceholderFragment();
}
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setTag(String.valueOf(sectionNumber));
fragment.setArguments(args);
return fragment;
}
public String getFTag(){
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
....}}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private Map<Integer, PlaceholderFragment> mPageReferenceMap = new HashMap<Integer, PlaceholderFragment>();
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
PlaceholderFragment pf = PlaceholderFragment.newInstance(position);
mPageReferenceMap.put(Integer.valueOf(position), pf);
return pf;
}
#SuppressWarnings("deprecation")
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferenceMap.remove(Integer.valueOf(position));
// mPageReferenceMap.remove(position);
}
public PlaceholderFragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
#Override
public int getCount() {
return 7;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
}
return null;
}
}

Related

Why are my floating action buttons not working properly in my ViewPager?

I have a ViewPager set up with my app and am trying to also set two floating action buttons, a left one and a right one, to do the same thing as the ViewPager, so that the user has a choice in terms of navigation. I'm trying to have it set so that the left button is invisible on the first page, and the right button is invisible on the last page, but the appearances of the buttons seem to be sporadic. I've tried debugging the app, and upon testing each situation, the appropriate code is executed, so I can't understand why this behavior is happening. Any help would be appreciated.
TestFragment:
public class TestFragment extends Fragment {
public static final String ARG_ID = "Id";
private int Id;
private String title;
private TextView titleTV;
private String description;
private TextView descriptionTV;
private int number;
private TextView numberTV;
private FloatingActionButton leftBtn;
private FloatingActionButton rightBtn;
public static TestFragment newInstance(int Id) {
Bundle args = new Bundle();
args.putSerializable(ARG_ID, Id);
TestFragment fragment = new TestFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_test, container, false);
Id = getArguments().getInt(ARG_ID);
title = Test.testData[Id].getTitle();
description = Test.testData[Id].getDescription();
number = Test.testData[Id].getNumber();
titleTV = view.findViewById(R.id.title);
titleTV.setText(title);
descriptionTV = view.findViewById(R.id.description);
descriptionTV.setText(description);
numberTV = view.findViewById(R.id.number);
numberTV.setText(String.valueOf(number));
leftBtn = view.findViewById(R.id.left_btn);
rightBtn = view.findViewById(R.id.right_btn);
toggleButtons();
leftBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
testViewPager.setCurrentItem(--index);
toggleButtons();
}
});
rightBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
testViewPager.setCurrentItem(++index);
toggleButtons();
}
});
return view;
}
public void toggleButtons() {
if(index == 0) {
leftBtn.setVisibility(View.INVISIBLE);
}
else if(index == Test.testData.length - 1) {
rightBtn.setVisibility(View.INVISIBLE);
}
else {
leftBtn.setVisibility(View.VISIBLE);
rightBtn.setVisibility(View.VISIBLE);
}
}
}
TestPagerActivity:
public class TestPagerActivity extends AppCompatActivity {
public static int index;
public static ViewPager testViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_pager);
index = (int) getIntent().getSerializableExtra(EXTRA_ID);
testViewPager = findViewById(R.id.test_view_pager);
FragmentManager fragmentManager = getSupportFragmentManager();
testViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
#Override
public Fragment getItem(int position) {
return TestFragment.newInstance(position);
}
#Override
public int getCount() {
return Test.testData.length;
}
});
for(int i = 0; i < Test.testData.length; i++) {
if(i == index) {
testViewPager.setCurrentItem(i);
break;
}
}
}
}

send data from popup to tabbed activity having fragments

mainActivity has button. After button is clicked a popup message show having a button and a TextInputLayout.
data is sent to a tabbed acticity having 2 fragments and
the data is shown in textview of first fragment. Error is the data wont show in the textview while running
adapter for 2 fragments--
public class adapter extends FragmentPagerAdapter {
public adapter(#NonNull FragmentManager fm) {
super(fm);
}
#NonNull
#Override
public Fragment getItem(int position) {
Fragment fragment;
if (position == 1) {
fragment = new SecondFragment();
} else {
fragment = new FirstFragment();
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
String title = null;
if (position == 0) {
title = "TextView";
} else if (position == 1) {
title = "Listview";
}
return title;
}
}
mainActivity
myDialog = new Dialog(this);
}
//for for joining match
public void ShowPopup(View view) {
myDialog.setContentView(R.layout.popup);
myDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
myDialog.show();
name = myDialog.findViewById(R.id.ig_name);
String igname = Objects.requireNonNull(name.getEditText()).getText().toString();
entry = myDialog.findViewById(R.id.entry);
entry.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), secondActivity.class);
intent.putExtra("igname", igname);
startActivity(intent);
finish();
});
}
}
my firstFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_first, container, false);
secondActivity activity = (secondActivity) getActivity();
TextView output = view.findViewById(R.id.textshow);
Bundle results = activity.getMyData();
String value1 = results.getString("value");
output.setText(value1);
return view;
}
secondActivity (intent is transfered from popup window)
public class secondActivity extends AppCompatActivity {
private String name;
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new adapter(getSupportFragmentManager()));
tabLayout = findViewById(R.id.tabs_layout);
tabLayout.setupWithViewPager(viewPager);
Intent intent = getIntent();
name = intent.getExtras().getString("igname");
}
public Bundle getMyData() {
Bundle bundle = new Bundle();
bundle.putString("value", name);
return bundle;
}
}

How to pass retrofit data in bundle to view pager fragments from activity?

In my activity i am receiving a game id from previous activity and using this id i am getting list of data from api. The method ("ApiCheats") in activity is used to get lis t of data.
I want to pass this list to my fragment in view pager, for this i used bundle but in fragment the bundle is null.
How should i pass bundle list to fragment , this data i am receiving through retrofit.
This is the Activity
public class GameListCheatsActivity extends AppCompatActivity {
private final String TAG = GameListCheatsActivity.class.getSimpleName();
public List<Cheats> Cheats;
ArrayList cheats = new ArrayList<Cheats>();
// public RecyclerView recyclerView;
String Gameid;
ViewPager viewPager;
ViewPagerAdapter adapter;
TabLayout tabLayout ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list_cheats);
// recyclerView = (RecyclerView) findViewById(R.id.recycler_id);
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
// recyclerView.setLayoutManager(linearLayoutManager);
// recyclerView.setHasFixedSize(true);
Gameid = getIntent().getStringExtra("GameID");
tabLayout = (TabLayout) findViewById(R.id.tab_layout_id);
viewPager = (ViewPager) findViewById(R.id.viewpager_id);
adapter = new ViewPagerAdapter( getSupportFragmentManager());
ApiCheats();
adapter.AddFragment(new Fragment_Cheats(),"GameCheats");
adapter.AddFragment(new Fragment_Favourites(),"Favourites");
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
if(state == 0){
View inflatedView = getLayoutInflater().inflate(R.layout.cheatitem, null);
}
if(state == 1){
View inflatedView = getLayoutInflater().inflate(R.layout.cheatitem, null);
}
}
});
}
public void ApiCheats()
{
ApiUtil.getServiceClass().getAllCheats(Gameid).enqueue(new Callback<List<Cheats>>() {
#Override
public void onResponse(Call<List<Cheats>> call, Response<List<Cheats>> response) {
if(response != null)
{
if(response.isSuccessful())
{
Cheats = response.body();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("cheatslist", (ArrayList<? extends Parcelable>) Cheats);
Fragment_Cheats fragment_cheats = new Fragment_Cheats();
fragment_cheats.setArguments(bundle);
}
}
Log.d(TAG, "Returned count " + Cheats.size());
GameListCheatsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// CheatsAdapter adapter = new CheatsAdapter(getApplicationContext(), Cheats);
// recyclerView.setAdapter(adapter);
}
});
}
#Override
public void onFailure(Call<List<Cheats>> call, Throwable t) {
Log.d(TAG, "error loading from API");
}
});
}
}
this is one of the fragments class
public class Fragment_Cheats extends Fragment {
View v;
private RecyclerView mrecyclerview;
private List<Cheats> lstGameCheats;
public Fragment_Cheats()
{
}
// #Override
// public void onCreate(#Nullable Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
//
// Bundle bundle = this.getArguments();
// if (bundle != null) {
// lstGameCheats = bundle.getParcelable("cheatslist");
// }
//
// }
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_fragment__cheats, container, false);
mrecyclerview = (RecyclerView)v.findViewById(R.id.recyclerview_cheats);
Bundle bundle = this.getArguments();
if (bundle != null) {
lstGameCheats = bundle.getParcelable("cheatslist");
}
CheatsAdapter recyclerAdapter = new CheatsAdapter(getContext(),lstGameCheats);
mrecyclerview.setLayoutManager(new LinearLayoutManager(getActivity()));
mrecyclerview.setAdapter(recyclerAdapter);
return v;
}
}
this is view pager adapter
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> lstFragment = new ArrayList<>();
private final List<String> lstTitles = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return lstFragment.get(position);
//return null;
}
#Override
public int getCount() {
return lstTitles.size();
//return 0;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return lstTitles.get(position);
}
public void AddFragment(Fragment fragment,String title){
lstFragment.add(fragment);
lstTitles.add(title);
}
}
You should set the Cheats to the Fragment which have added to your ViewPagerAdater, but according to your code you just set the data to a new fragment instance.
According to the Fragment_Cheats code, if you want to invoke getArgument() in onCreate() method, you should invoke fragment.setArgument() before the fragment add to the ViewPagerAdapter.
But in your situation it is not possible, because the data get from the network.
So, two step
Set data to the correct Fragment_Cheats instance
Notify Fragment_Cheats data changed, refresh the View state in the fragment
Replace your onResponse()
#Override
public void onResponse(Call<List<Cheats>> call, Response<List<Cheats>> response) {
if(response != null)
{
if(response.isSuccessful())
{
Cheats = response.body();
Fragment_Cheats fragment_cheats = adapter.getCheatFragment()
fragment_cheats.setDatas(Cheats);
}
}
Log.d(TAG, "Returned count " + Cheats.size());
GameListCheatsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// CheatsAdapter adapter = new CheatsAdapter(getApplicationContext(), Cheats);
// recyclerView.setAdapter(adapter);
}
});
}
Fragment_Cheats add setDatas() method
public void setDatas(List<Cheats> datas) {
this.lstGameCheats = datas;
// and set the datas to the RecylerView adapter
recyclerviewAdapter.notifyDataSetChanged();
}

how to open a new fragment using RecyclerView

I am trying to make an app that which is like a place picker, meaning you write down a product like pizza or burger, and u get all the places around you that have pizza or burger.
now I'm using RecyclerView in my fragment and i also have Map fragment
when you click on an item in the RV, it will show its location on the map using the map fragment.
my problem is when I'm clicking on an item in the recyclerview i get nullpointerexception
here is my code of the first fragment
public class PlacesFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> , AdapterView.OnItemClickListener{
ClickListener listener;
static Places places;
PlacesAdapter adapter;
public FragmentManager fm;
MyMapFragment mapFragment;
Cursor cursor;
public PlacesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View myFragView= inflater.inflate(R.layout.fragment_places, container, false);
RecyclerView rv= (RecyclerView)myFragView.findViewById(R.id.placesRecyclerView);
//this create the line beetween every list to do so i have import to the build gradle a flexible divider
rv.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).color(Color.BLACK).build());
cursor = getActivity().getContentResolver().query(CONTENT_URI, null, null, null, null);
adapter= new PlacesAdapter(cursor, getActivity());
rv.setAdapter(adapter);
adapter.notifyItemRangeChanged(cursor.getPosition(), cursor.getCount());
adapter.notifyDataSetChanged();
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
rv.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), rv, new ClickListener() {
#Override
public void onPlaceClick(String latlng) {
//when i click on a place it will go to the map fragment
// Toast.makeText(getActivity(), "on click" + position, Toast.LENGTH_LONG).show();
/* FragmentManager fm = getFragmentManager();
// get the map object from the fragment:
mapFragment = MyMapFragment.newInstance(places);
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragmantContainer, mapFragment, "map");
ft.addToBackStack(null);
ft.commit();*/
}
})
);
// getLoaderManager().initLoader(1, null,);
return myFragView;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (ClickListener)context;
} catch (ClassCastException e) {
throw new ClassCastException("context " + context.toString()
+ "must implement PlacesFragmantListener!");
}
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// CursorLoader c=getContext().getContentResolver().query(PlacesContract.Places.CONTENT_URI, null, null,null, null);
return new CursorLoader(getActivity(),CONTENT_URI, null, null,null, null );
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
public static interface PlacesFragmantListener {
public void onLocationSelected(Places places);
}
class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
private ClickListener clickListener;
MyMapFragment mapFragment;
public RecyclerTouchListener(Context context, RecyclerView recyclerView, ClickListener clickListener){
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener(){
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
}
});
this.clickListener = clickListener;
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(),e.getY());
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
Log.d("PlaceAdapter", "onTouchEvent"+e);
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
}
here is my map fragment
public class MyMapFragment extends Fragment {
public MyMapFragment(){
}
public static MyMapFragment newInstance(Places places) {}
if (places == null) {
places = new Places(0,"no Location selected","","", "");
}
// the arguments to pass
Bundle args = new Bundle();
args.putString("location", places.getLocation());
args.putDouble("lat", location.getLat());
args.putDouble("lon", location.getLon());
MyMapFragment mapFragmant = new MyMapFragment();
mapFragmant.setArguments(args);
return mapFragmant;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.mapfragment, container, false);
Bundle b=getArguments();
String latlng= b.getString("location");
Log.d("fragment...", latlng);
String[] latlongarr= latlng.split(",");
double lat= Double.parseDouble(latlongarr[0]);
double lon= Double.parseDouble(latlongarr[1]);
FragmentManager fm = getFragmentManager();
MapFragment mapFragment = (MapFragment) fm.findFragmentById(R.id.map);
// get the map object from the fragment:
GoogleMap map = mapFragment.getMap();
if(map!= null) {
// setup the map type:
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
// setup map position and zoom
LatLng position = new LatLng(b.getDouble("lat"), b.getDouble("lon"));
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(position, 15);
map.moveCamera(update);
}
return view;
}
}
here is my adapter
public class PlacesAdapter extends RecyclerView.Adapter<PlacesAdapter.PlaceHolder> {
private Cursor cursor;
private Context context;
private static TextView placeName, address, distance, url;
public static ImageView imgplace;
public static PlaceHolder.ClickListener clickListener;
private static Places place;
private DataSetObserver mDataSetObserver;
MyMapFragment mapFragment;
private boolean mDataValid;
ClickListener listener;
public PlacesAdapter(Cursor cursor, Context context) {
this.context = context;
this.cursor = cursor;
mDataSetObserver = new NotifyingDataSetObserver();
if (cursor != null) {
cursor.registerDataSetObserver(mDataSetObserver);
}
}
#Override
public PlaceHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// cursor.setNotificationUri(context.getContentResolver(), CONTENT_URI);
LayoutInflater inflater = LayoutInflater.from(context);
View myView = inflater.inflate(R.layout.single_place, parent, false);
PlaceHolder placeHolder = new PlaceHolder(myView, new PlaceHolder.PlacesFragmantListener() {
#Override
public void onLocationSelected(Places places) {
}
});
return placeHolder;
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(true);
}
#Override
public void onBindViewHolder(PlacesAdapter.PlaceHolder holder, final int position) {
if (cursor.moveToPosition(position)) {
int column_number = cursor.getColumnIndex(PLACES_NAME);
String name = cursor.getString(column_number);
placeName.setText(name);
int column_number2 = cursor.getColumnIndex(PLACES_ADDRESS);
String adr = cursor.getString(column_number2);
address.setText(adr);
int column_number3 = cursor.getColumnIndex(PLACES_DISTANEC);
String dis = cursor.getString(column_number3);
distance.setText(dis);
int column_number4 = cursor.getColumnIndex(PLACE_PHOTO);
String photo = cursor.getString(column_number4);
if(!photo.equals(""))
{
GoogleAccess.myImageDownloader loader= new GoogleAccess.myImageDownloader(imgplace);
loader.execute(photo);
}
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Item click at " + position, Toast.LENGTH_LONG).show();
if(cursor.moveToPosition(position))
{
String latlong= cursor.getString(cursor.getColumnIndex(PlacesDbconstanst.CurrentPlaces.PLACES_DISTANEC));
listener.onPlaceClick(latlong);
}
}
});
}
public void setClickListener(PlaceHolder.ClickListener clickListener){
this.clickListener = clickListener;
}
#Override
public int getItemCount() {
return cursor.getCount();
}
public static class PlaceHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
PlacesFragmantListener listener;
public PlaceHolder(View itemView, PlacesFragmantListener placesFragmantListener) {
super(itemView);
listener = placesFragmantListener;
placeName = (TextView) itemView.findViewById(R.id.placeNametextView);
address = (TextView) itemView.findViewById(R.id.addressTextView);
distance = (TextView) itemView.findViewById(R.id.distanceTextView);
imgplace = (ImageView) itemView.findViewById(R.id.placesImageViewId);
imgplace.setOnClickListener(this);
itemView.setOnClickListener(this);
}
RecyclerView rv;
#Override
public void onClick(View v) {
if(clickListener!=null){
clickListener.itemClicked(v, getPosition());
}
}
public static interface PlacesFragmantListener {
void onLocationSelected(Places places);
}
public interface ClickListener{
public void itemClicked (View view, int position);
}
}
private class NotifyingDataSetObserver extends DataSetObserver {
#Override
public void onChanged() {
super.onChanged();
mDataValid = true;
notifyDataSetChanged();
}
#Override
public void onInvalidated() {
super.onInvalidated();
mDataValid = false;
notifyDataSetChanged();
}
}
}
can you tell me what i did wrong
here is the log comment
03-30 04:55:28.042 2318-2318/com.myapps.pinkas.placesofintrest W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa4c8cb20)
03-30 04:55:28.042 2318-2318/com.myapps.pinkas.placesofintrest E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapps.pinkas.placesofintrest, PID: 2318
java.lang.NullPointerException
at com.myapps.pinkas.placesofintrest.PlacesAdapter$2.onClick(PlacesAdapter.java:112)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
distance = (TextView) itemView.findViewById(R.id.distanceTextView);
is this line come in 112 in your class file, it's seems like, you have not defined view id or view in XML, please check line number 112 in PlacesAdapter.class
Problem 1: Setting onclick listener twice. In onbindviewholder you have put holder.itemView.setOnclicklistener and then again in static class viewholder, you have put itemview.setOnclickListener. When you assign setOnclicklistener inside the static viewholder class, it means it will behave in a particular way uninfluenced by values present in any other views (like textview, imageview) or any such factors which depend on some 'value' property of the views. For most purposes you should have setOnClicklistener onto the itemview/textview/etc inside the static viewholder class which in your case is called placeholder.
Problem 2: Here is the reason why I believe you are getting NullPointerException. onbindviewholder has access to only the views declared in static viewholder class. If you want itemview to be accessible to onbindviewholder then make the following changes:
public static class PlaceHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
PlacesFragmantListener listener;
View iv;
public PlaceHolder(View itemView, PlacesFragmantListener placesFragmantListener) {
super(itemView);
iv = (View)itemView;
//then rest of the code
Now in your onbindviewholder write the following instead of holder.itemview.setonclicklistener
holder.iv.setonclicklistener...
Problem 3: in your static viewholder, you have put:
imgplace.setOnClickListener(this);
itemView.setOnClickListener(this);
itemview is the layout in which imgplace exists. And you have setonclicklistener on both of them. This is like putting a button on a button. It makes no sense. I think this will lead you into lot of mess. For some reason you want both to perform the same function on being clicked (you have put 'this' inside setOnClickListener). This is completely illogical. So set the clicklistener to either imgplace or itemview but not both

Getting a Fragment inside a ViewPager in Android using getRegisteredFragment returns null

I've been searching a lot and I can't make it work.
I have a problem trying to get fragments inside a viewpager with a tabstrip.
I've implemented a SparseArray as I read here and several methods that I found here but I can't make it work.
The thing is that everytime I call adapter.getRegisteredFragment(position).. I always receive null unless I made it inside the onPageSelected event of the tabsStrip, there it works.. but I don't want to get the fragments there.
Those are my classes:
My fragment:
public class WeekFragment extends Fragment implements View.OnClickListener
{
private static final String ARG_POSITION = "position";
private int position;
private LinearLayout[] btns;
public static WeekFragment newInstance(int position) {
WeekFragment f = new WeekFragment();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
f.setArguments(b);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
position = getArguments().getInt(ARG_POSITION);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
fillFragment();
}
private void fillFragment()
{
// Irrelevant stuff..
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
return inflater.inflate(R.layout.week_fragment, container, false);
}
#Override
public void onClick(View v)
{
// Irrelevant stuff
}
public LinearLayout[] getBtns()
{
return btns;
}
public void setBtns(LinearLayout[] btns)
{
this.btns = btns;
}
}
My adapter:
public class WeekAdapter extends FragmentPagerAdapter
{
Calendar cal;
Context context;
SparseArray<Fragment> registeredFragments;
private String[] TITLES = new String[6];
public WeekAdapter(FragmentManager fm, Context context)
{
super(fm);
registeredFragments = new SparseArray<>();
this.context = context;
fillTitles();
}
private void fillTitles()
{
// Fill titles
}
#Override
public CharSequence getPageTitle(int position)
{
return TITLES[position];
}
#Override
public int getCount()
{
return TITLES.length;
}
#Override
public Fragment getItem(int position)
{
return WeekFragment.newInstance(position);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
and my activity:
public class MyActivity extends FragmentActivity
{
private PagerSlidingTabStrip tabs;
private ViewPager pager;
private WeekAdapter adapter;
private List<DayResumeItem> listDayResumesItems;
private User u;
private View mProgressView;
private View mRotaView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rota2);
mProgressView = findViewById(R.id.view_progress);
mRotaView = findViewById(R.id.view_rota);
this.u = this.getIntent().getExtras().getParcelable(getString(R.string.parcel_user));
// Initialize the ViewPager and set an adapter
pager = (ViewPager) findViewById(R.id.pager);
adapter = new WeekAdapter(getSupportFragmentManager(), getApplicationContext());
pager.setAdapter(adapter);
// Bind the tabs to the ViewPager
tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
tabs.setViewPager(pager);
tabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
WeekFragment f = (WeekFragment)adapter.getRegisteredFragment(week);
// Do stuff.. Here, f is not null. Here I can work, but I don't want to.
}
#Override
public void onPageSelected(int position)
{
}
#Override
public void onPageScrollStateChanged(int state)
{
}
});
WeekFragment f = (WeekFragment)adapter.getRegisteredFragment(week);
// Do stuff.. Here, f is null and I can't work.
}
#Override
protected void onResume()
{
super.onResume();
getList();
}
}
It is everytime I call adapter.getRegisteredFragment(position) on my activity where it crash because it always return null..
I swear that I've been searching a lot but I'm unable to make it work.
Thank you very much everybody!
I think my problem was that I was calling this adapter.getRegisteredFragment(position) in the onCreate of my activity, and in the onCreate, the viewpager is still not fully loaded and the registeredFragments aren't still instantiated, so the list is still empty..
If you move this callings to another place when the viewpager is fully loaded, it will work.
The items in registeredFragments are initialized in instantiateItem() method, which should be called during the process of drawing views. And this drawing process happens after onCreate()/onResume().
I am not sure what stuff you want to do by getting Fragment in onCreate(), but generally it is not a good idea since the Fragment is not initialized at that moment. You should access the fragment in onPageSelected() as you said.

Resources