Reputation: 331
Recently i'm working on my app to make it load faster and work better, i'm using navigation drawer in my MainActivity:
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camara) {
LoadJson asyncTask = (LoadJson) new LoadJson(new LoadJson.AsyncResponse() {
@Override
public void processFinish(JSONArray output) {
//Here you will receive the result fired from async class
//of onPostExecute(result) method.
//Set the fragment initially
MainFragment fragment = new MainFragment(output);
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
// Handle the camera action
}
}).execute();
} else if (id == R.id.nav_gallery) {
//Set the fragment initially
GalleryFragment fragment = new GalleryFragment();
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
} else if (id == R.id.nav_search) {
//Set the fragment initially
FetchResualt fragment = new FetchResualt();
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
// Handle the camera action
} else if (id == R.id.nav_manage) {//
Bundle bundle = new Bundle();//
bundle.putInt("someStr",ID_OF_BEACH);//
//Set the fragment initially//
FragmentBeach fragment = new FragmentBeach();//
fragment.setArguments(bundle);//
FragmentTransaction fragmentTransaction =//
getSupportFragmentManager().beginTransaction();//
fragmentTransaction.replace(R.id.fragment_container, fragment);//
fragmentTransaction.commit();//
// Handle the camera action
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
As you can see if we push the first menu if (id == R.id.nav_camara)
it will pass a JSONArray
to a Fragment class and it take like 4-5 seconds to load. So if the user navigates between menus every time he goes to nav_camara
it make the app a 4 second freeze to load and as you can see everytime we choose a menu item it will recreate a new copy of fragment, so even if I make: setRetainInstance(true);
in my fragment class it wont work.
What solution you suggest to prevent the app to recreate a new fragment each time we choose a menu item?
Upvotes: 0
Views: 1418
Reputation: 6555
You will need to keep a SparseArray<Fragment>
to keep the instances in memory.
Follow these steps:
create a field in your Activity:
SparseArray<Fragment> myFragments;
initialise it in the onCreate()
like:
myFragments = new SparseArray<Fragment>();
update your onNavigationItemSelected()
:
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camara) {
// get cached instance of the fragment
fragment = myFragments.get(INT_CONSTANT_FOR_CAM_FRAGMENT);
// if fragment doesn't exist in myFragments, create one and add to it
if (fragment == null) {
fragment = new MainFragment();
myFragments.put(INT_CONSTANT_FOR_CAM_FRAGMENT, fragment);
}
// now load the fragment
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
// do the rest with others as well.
}
AsyncTask
thing inside your MainFragment
's onActivityCreated()
or a similar lifecycle method.Above way will let you reuse the fragments and move the logic to their correct location (your Activity shouldn't know how MainFragment
loads data to initiate itself, but of course you can still keep it there, though not recommended).
Upvotes: 2
Reputation: 136
Declare them globally
GalleryFragment galleryFrag = new GalleryFragment();
FragmentTransaction ft;
FragmentManager fm;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
fm = getSupportFragmentManager();
...
}
then on your navigation selection
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_search) {
ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, galleryFrag).commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Upvotes: 0
Reputation: 8281
You can add a TAG
while push a new fragment to the container. Then use FragmentManager#findFragmentByTag
to find any fragment previously added with the same tag.
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment oldFragment = manager.findFragmentByTag(tag);
if (oldFragment != null)
transaction.replace(R.id.fragment_container, oldFragment, tag);
else
transaction.replace(R.id.fragment_container, newInstanceOfFragment, tag);
transaction.commit();
Upvotes: 0