22

I changed the locale of my application programmatically, like following:

Resources res = context.getResources();

 DisplayMetrics dm = res.getDisplayMetrics();
 android.content.res.Configuration conf = res.getConfiguration();
 conf.locale = new Locale("cn");
 res.updateConfiguration(conf, dm);

After this, I would like to refresh my currently displayed fragment's view to display with new locale settings.

So, I firstly get the current fragment (that's the latest one in backstack):

BackStackEntry latestEntry=fragMgr.getBackStackEntryAt(fragMgr.getBackStackEntryCount()-1);
String str=latestEntry.getName();
Fragment fragment=fragMgr.findFragmentByTag(str);

After I get the currently showing fragment, I would like to refresh its view, but how to do it? Is it possible in Android to refresh the view of a fragment

Leem.fin
  • 40,781
  • 83
  • 202
  • 354

4 Answers4

35

You can simply detach and attach fragment as below

    Fragment currentFragment = getFragmentManager().findFragmentByTag("FRAGMENT");
    FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
    fragTransaction.detach(currentFragment);
    fragTransaction.attach(currentFragment);
    fragTransaction.commit();

This will refresh the view and locale will change

ZeeShaN AbbAs
  • 1,365
  • 2
  • 15
  • 31
  • But how can i send some data to fragment? I am getting a blank view on the top now. – Sunit Kumar Gupta Jun 05 '14 at 13:18
  • How are you sending data to fragment? You should use fragment.setArguments(Bundle extras); method to pass data. and when you refresh fragment the data will persist so you won't have any problem. – ZeeShaN AbbAs Jun 05 '14 at 14:43
  • yes i do this but Fragment life cycle is not being called for MyFragment Class. – Sunit Kumar Gupta Jun 06 '14 at 04:53
  • 2
    This seems to work only for fragments that are attached to the activity programatically. For fragments that have been instanciated by the XML layout file of the activity only onActivityCreated is called when the activity is resumed and therefore the fragment shows still the old localization. – Nantoka Sep 27 '14 at 23:08
  • 5
    A quick note to help avoid problems for future users: In the google group here: https://groups.google.com/forum/#!topic/android-platform/QlkLMsncDwg Dianne Hackborn states that detaching a Fragment in a `FragmentTransaction` will not call `onAttach()` or `onDetach()` for that `Fragment`. Thus, don't rely on these lifecycle methods for refreshing your view(s). – jwir3 Jan 04 '15 at 01:56
  • If you're using the Support Library, instead of getFragmentManager(), use getFragmentManager(). – Javad Jan 20 '15 at 20:32
  • In my case, when I had only one Fragment in the back stack, it refreshed fine. When I had more than one, onDetach wasn't called, so I had to call detach/attach twice to make it work. Sounds ugly but that's how it happened. – Teo Inke Apr 06 '15 at 16:08
  • How to know which is current fragment? – IntoTheDeep Jun 17 '16 at 08:39
  • Does that go in the Activity or Fragment? Also, how do I find the tag? – Si8 Oct 20 '16 at 10:00
  • It goes under activity and you can only get fragment by tag if you have dynamically added and passed the tag (which is a simple string) however you can also get current fragment by id. More info about that http://stackoverflow.com/questions/8532462/how-to-get-the-fragment-instance-from-the-fragmentactivity – ZeeShaN AbbAs Oct 20 '16 at 14:12
  • Also, fragments added to a LinearLayout will move to the bottom when de- and attached like this. – Erik Aug 14 '17 at 07:36
  • and you can tag like this fragmentTransaction.replace(android.R.id.content, fragment2,"tagfragment2"); – Innocent Sep 12 '17 at 11:54
  • Detaching and re-attaching a fragment in a single transaction is not guaranteed to work, the system may decide to optimize and just do nothing with the fragment. See [my answer](https://stackoverflow.com/a/68534388/5701177) for a better approach. – gardenapple Aug 04 '21 at 15:00
2

You could create a listener, which will be called when the locale changes. This will then remove the Fragment, and re add the Fragment. Your new locale should then be picked up.

Mimminito
  • 2,803
  • 3
  • 21
  • 27
  • 3
    Where should the listener be created? can you please be more specific on how to do it? – Leem.fin Mar 27 '12 at 12:12
  • Create your own interface, which your activity implements. Then register the listener with your fragment in onAttach(). When you change the locale, call the method in the interface, and remove/re-add the fragment – Mimminito Mar 27 '12 at 15:07
1

The solution that finally worked for me was this, in Kotlin:

        val manager = requireActivity().supportFragmentManager
        
        manager.beginTransaction().let {
            it.detach(this)
            it.commit()
        }
        manager.executePendingTransactions()
        manager.beginTransaction().let {
            it.attach(this)
            it.commit()
        }

Notice how I'm detaching and re-attaching the fragment in separate transactions. From the Android docs:

As a FragmentTransaction is treated as a single atomic set of operations, calls to both detach and attach on the same fragment instance in the same transaction effectively cancel each other out, thus avoiding the destruction and immediate recreation of the fragment's UI. Use separate transactions, separated by executePendingOperations() if using commit(), if you want to detach and then immediately re-attach a fragment.

gardenapple
  • 146
  • 1
  • 12
0

I finally found the solution to it! Just run your view update code in the UI thread

Example -

 getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                user_arrayList.add(name);
                adapter.notifyDataSetChanged();
                tv_total_users.setText("Total Users : "+user_arrayList.size());
            }
        });

Finally found this solution after trying for almost 4-5 hours!

  • Even if the question is 2 years old... IMHO this is the worst you can do. You should really use `onCreate` and `onResume`. – Emaborsa Feb 08 '20 at 09:54