Refreshing For Constant Fragments

2019-08-23 03:03发布

问题:

I will try to describe the problem and simplify it At my app, I have one activity, and 3 fragments and I swap through them at Phone Mode. and these fragments I made their fragments instances as constant objects at main activity so the internal objects which are not related to fragment life cycle stay hold their values even this fragment doesn't visible (Logically the objects will release when the fragment object is destroyed)

Now, when I tried to make my app support tablet, I made the 3 fragments display at the same time but there's something strange is happened.

Say fragment A hold list of items and fragment B show the detail of selected item. and there is an object at fragment B. this object holds the selected item id [All fragments display at the same time in one activity as I mentioned before], this object save current item id value when the fragment B created, and save the new selected item id when onDestroyView() method called at fragment B.

Now, when I start my app, I add the fragment A, and when I select item from list the fragment B is added and its object hold the selected value. for now all things are right. when I select another item, I just need to refresh the fragment B as the internal object will hold the new selected id so I did this line

 Fragment fragment = mFragmentManager.findFragmentByTag([fragmentId]);
 mFragmentManager.beginTransaction().detach(fragment).attach(fragment).commit();

but the result I got is that the fragment B get the previous state which it was on, what I mean is that the internal object hold the first item id i selected.

I tried to test the internal object before fragment refreshing

 Fragment fragment = mFragmentManager.findFragmentByTag([fragmentId]);
 Log.e("my object","value" + String.valueOf(fragment.getValue));
 mFragmentManager.beginTransaction().detach(fragment).attach(fragment).commit();

and It was holding the right item id value which have to display ... !! Also I passed the constant value instead to ensure but I get the same strange result

 Fragment fragment = mFragmentManager.findFragmentByTag([fragmentId]);
 mFragmentManager.beginTransaction().detach(fragment).attach(FRAGMENT).commit();

So what's happen ?? Logically it have to work as I think.

pic for the original code and this is the log result (Note: 2 is the next item i selected) and this is the next log result after fragment B is refreshed (Note this log inside fragment B and id 3 is the first Item i selected) the expected result is 2

回答1:

Finally I understood the fragment transaction behavior and how it works ...

Once you add/replace new fragment to Fragment Transaction you object is saved as initial state within Fragment Manager and when you try to detach the fragment and reattach [the same object] the Fragment Manager will get the object state which you passed it before to add()/replace() function. So that's the reason of the result I got.

To simplify it.

  • Suppose that you have an Class A extends from Fragment class and this class contains Integer object have no value and have Set()/Get() methods.

  • Now create an instance from this Class A and call Set() function and pass value 1 to it. Then pass this instance to Manager Transaction by add()/replace()` method.

  • Now try to call Set() function and change the Integer object to another value.

  • Detach the class A and reattach it and check the value of this object, you will get that the value of object return to initial value you assigned before passing the object to Manger Transaction

Beside that there's an important note ... Fragment Transaction Actions like add(), replace(), remove() ... don't work at main thread and that's the reason of using commit() method and commitNow() method .. because when you use commit() your action will add to Fragment Transaction Queue so it will be executed after a bit of time but not now that's upon its order inside the queue, and so that you have another method called commitNow() to make your action execute immediately.