My app has the next structure, I have the Mainactivity where I have my viewPager. Inside this viewpager I add new fragment Activities. These Fragment Activities have a TextView with their names, I have created a OnlongClickListener in the textview so that when you OnlongClick in the textview the fragment Activity gets removed from the list in the viewpager I have in the main Activity.
I've tried to use in the fragment Activity the next code :
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
but the result is an empty space in the position where the deleted fragment was.
I think the solution would be calling mypageradapter.notifyDataSetChanged() in the fragment Activity but the thing is that the viewPager and the pagerAdapter are created in the mainActivity and I want to notify the changes in the fragment activity.
How can I call mypageradapter.notifyDataSetChanged() from the fragment activity?
In this moment I have a solution for this problem but I don't think this solution is the best one, when I delete the fragment I create an intent for the mainActivity and then I StartActivity(intent). In the mainActivity onStart method I call mypageradapter.notifyDataSetChanged() and then the empty spaces dissapear and the fragment list is sorted correctly. This solution is really slow and rough.
I would appreciate a better solution for my problem.
P.D: For help I have MyPagerAdapter class inside the mainActivity.
Related
I have encountered some problems in "recreating" an adapter from the recyclerView in the onResume method.
Basically, this is my scheme.
MainActivit -ViewPager
- fragment A (has a recyclerView)
- fragment B (nop)
- fragment C (nop)
- fragment D (it has the same recyclerView as the framgnet A)
onResume I always call for
> myCustomAdapter adapter = new myCustomAdapter (
> mListItems,getContext(),ParseUser.getCurrentUser().getObjectId(),
> "type");
> recyclerView.setAdapter(adapter);
but this causes some problems, like when I go back to MainActivity from another activity. For example.
Activityt A
- click on item in recylerView
- start Activity B
Activity B
user does some actions, sees some news, and returns to Activity A.
Activity A
recreates the adapter and set recyclerView.setAdapter (new Adapter);
this is slow, causes a delay of 2 seconds after onBackPressed is pressed in Activity B.
I also have a setMenuVisibility method that also does the same thing as onResume, because as informed in fragment D, I have the recyclerView in fragment A, so if a user makes some change in the recyclerView that is in fragment D, I need update the recyclerView of fragment A when the user returns to it.
Why the same recyclerView in Fragment D is in Fragment A?
We can consider the following, in fragment A, I have a recyclerView that contains only the "user interests", and in fragment D, I have user information such as user name, photo, etc ... and also the "user interests".
Conclusion: The problem is when I return from Activity B to Activity A, and when I alternate between fragment A and fragment D in viewPager, this causes a delay for the re-creation of the adapter.
What should I do in this situation?
I apologize for this horrible English, I'm using google translator.
It is a Scope Problem. You need to define adapter in somewhere class member.
If you want the data presented in Fragment A and Fragment D different, then make adapter as a member of each other, and init it in each Fragment.onCreate(). So it won't recreate adapter evert time. (Make sure ViewPager has enough cache number, or it will still recreate the whole non-cached Fragment)
If you want the FragmentA and FragmentD display identical data or part of the same data, create adapter in MainActivity.onCreate and pass it as parameters into FragmentA, FragmentD.
It is not need to recreate adapter every time onResume because it's really a heavy job. No need to change any view layer attributes. Make sure the data(adapter) which you want to share is in the same scope or can pass to it.
For example:
//MainActivity
private Adapter adapter;
void onCreate(Bundle savedInstanceState){
//...other stuff
adapter = new myCustomAdapter (mListItems,getContext(),ParseUser.getCurrentUser().getObjectId(), "type");
}
public Adapter getAdapter(){ return adapter;}
//FragmentA or FragmentD
void onCreateView(){
MainActivity activity = (MainActivity) getActivity(); //This fragment should be created with `MainActivity`
recyclerView.setAdapter(activity.getAdapter());
}
Do not set set image using "src" attribute of ImageView when dealing with large images or multiple small images
Use an image loading library like Glide or Picasso.
The following snippet is for Glide v4
Glide.with(context).load(<url_or_res_id>).into(imageView)
You can pass url as string. Or if you are loading images from drawable, you can pass its resource id (eg. R.drawable.image_id)
Following the MvvmCross sample here
I am trying to show an activity, that contains a fragment. When I call ShowViewModel on the Activity, I see the activity, without the contained fragment.
If I call ShowViewModel on the Fragment, the Activity AND the Fragment are created.
Does this mean, in order to show a fragment I need to call ShowViewModel on the fragment and not on the parent activity? surly I should be able to call ShowViewModel on the activity and have that create the fragment.
Sorry if i'm missing something here.
Thanks
So I currently have an app that has 4 tabs (fragments). They are fragments A,B,C,D, in that order.
Fragment A is the first view opened (along with B because viewPager loads the view before and after the current view).
When I click a button in Fragment A, it sends Data back to MainActivity and then sends that data out to Fragments B and C.
However, this is where the issue comes into play. Since Fragment B was already called, the View isn't updated once I click the button and send the data over, but Fragment C is because the view wasn't called before.
Is there any way that I can remedy this?
You can do it a few ways right.
Just set the data to the fragment and have it update its views
Have all the fragments like B and C register themselves to recieve data from the MainActivity and when MainActivity gets it's data set you tell all the registered receivers of the new data
Recreate the fragment
Use an event bus and tell all subsribers of the new data and MainActivity, Fragment B would get notified of new data. Fragment C would get its data when created by MainActivity
I think this list is pretty endless tbh
The key here is the fragments need to fetch the data from the actvitiy aswell as be updated by the activity. In which case you need to break your UI update behaviour out of onCreateView and into its own updateUI() function. updateUI(MyData) can then be called from onCreateView and also called in a setMyData() on the fragment. Just make sure you check the isAdded flag in setMyData.
This pretty much says it all:
http://developer.android.com/training/basics/fragments/communicating.html
I used a simple fragment communicator that allows the activity to call the fragment, and the same for a fragment to talk to the activity.
You can change the views with the new data based on calling the method from within the activity. The way I do it is set the fragments in the activity then pass them into the page adapter this way I can call the methods within the fragment and implement the fragmentcommunicator interface on the fragments.
You can honestly even avoid the interface if you want, but if you are going to include the same method in all the fragments to talk to them it is easiest.
If you show code, I can show you a quick example.
I have a ViewPager with 3 fragments. One fragment downloads data from a website and displays it in TextViews. Now when the user clicks in the menu of the MainActivity on the item "refresh", the fragment should redownloads the data and displays it.
I tried to create a function refresh in the fragment's class and call it from the MainActivity's menu. That worked, but then it crashes because the app can't find the textview. The variable view is empty and it causes a null pointer exception.
What can I do to resolve this?
Many thanks!
From your fragmentactivity,
Fragment tehFraggerz = getSupportFragmentManager().findFragmentByTag(string);
where string is the tag. You set the tag of the fragments in the add, replace, etc methods.
Once you have your fragment, you can do
TextView tehTexterz = (TextView) tehFraggerz.getView().findViewById(R.id.tehText);
I'm trying to create a ViewPager with six fragments but only 2nd fragment to 5th fragment contain data that I want to show and the first fragment and the last fragment I want to be used to reload the data and set the position to the 2nd fragment again. The overall flow is like this :
1st (reload and go back to 2nd) <- 2nd fragment <-> 5th fragment -> 6th fragment (same with 1st)
what I've tried is I create a callback from the 1st fragment and 6th fragment like this
public static class callbackFragmentLoading implements callbackFragmentLoad {
#Override
public void onLoading() {
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(2,false);
}
}
and I passed the callback to the fragment constructor so I can called the onLoading function in the onActivityCreated. But I everytime I do it the application will be force closed and the logcat shows
recursive entry to executependingtransactions
is there any way to do this? or my method for doing it is wrong?
Thank You
is there any way to do this? or my method for doing it is wrong?
Messing with callbacks between Fragments of a ViewPager isn't probably such a good idea. Instead I would do it like this:
Don't load any data(like with a Loader) in the Fragments from the ViewPager, instead let the FragmentActivity do it(and the Fragments will get it through methods from the Activity).
Your two loading fragments(position 0 and 5) will call in their onResume method a reload action on the parent Activity(like a Loader restart)
At this moment the Activity will load/reload the data and when that finishes it will set the ViewPager to the correct items(either 1 or 4)
in the onResume method of the data fragments you'll refresh the fragment's data(here you may need to use some sort of signaling system because you'll need to duplicate the refresh code in the onCreateView(some fragments may have their view destroyed if they are far apart from the current visible position)).
As I don't know many things about the inner data fragment I've written a basic skeleton sample(without the data loading in the activity).