javaandroidandroid-fragmentsandroid-studioandroid-preferences

Update Fragment after going back from another activity


In my app, I have my MainActivity, in this activity there is a fragment which displays the following thing: "Hello, (yourname)". You can change "yourname" in the preferences activity. Here is the code for changing the name in the fragment:

public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            LayoutInflater lf = getActivity().getLayoutInflater();
            View rootView = lf.inflate(R.layout.fragment_frontpage, container, false);
            SharedPreferences pref= PreferenceManager.getDefaultSharedPreferences(getActivity());
            String text = pref.getString("example_text","");
            TextView textView = (TextView) rootView.findViewById(R.id.NameView);
            textView.setText(text);
            return rootView;
        }


    }

NameView is the id of the Textview for the name, "example_text" is the id for the preference key of the name-changer preference. Sounds good so far, right?

Well, now the problem: When changing the name in the preference activity, and thus the preference value of "example_text", I press back and the frontpage (my MainActivity), appears. BUT, the name doesn't change immediately, I have to kill the app in my taskmanager, or go to "about this app" and terminate the process. After that, and only then, the new name is being displayed in my fragment if I reopen the app again.

Well, I have figured I need somehow to update the fragment when going back to my MainActivity. Probably use onBackPressed. But the question is, how?

EDIT: Error when switching to landscape:

4-07 19:51:37.825    7831-7831/com.package.appname E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.package.appname, PID: 7831
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.package.appname/com.package.appname.Frontpage}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.package.appname.Frontpage$PlaceholderFragment: make sure class name exists, is public, and has an empty constructor that is public
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3912)
        at android.app.ActivityThread.access$900(ActivityThread.java:144)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.package.appname.Frontpage$PlaceholderFragment: make sure class name exists, is public, and has an empty constructor that is public
        at android.support.v4.app.Fragment.instantiate(Fragment.java:431)
        at android.support.v4.app.FragmentState.instantiate(Fragment.java:101)
        at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1833)
        at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:264)
        at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:122)
        at com.package.appname.Frontpage.onCreate(Frontpage.java:68)
        at android.app.Activity.performCreate(Activity.java:5933)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3912)
            at android.app.ActivityThread.access$900(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: java.lang.InstantiationException: class com.package.appname.Frontpage$PlaceholderFragment has no zero argument constructor
        at java.lang.Class.newInstance(Class.java:1563)
        at android.support.v4.app.Fragment.instantiate(Fragment.java:420)
            at android.support.v4.app.FragmentState.instantiate(Fragment.java:101)
            at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1833)
            at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:264)
            at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:122)
            at com.package.appname.Frontpage.onCreate(Frontpage.java:68)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3912)
            at android.app.ActivityThread.access$900(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: java.lang.NoSuchMethodException: <init> []
        at java.lang.Class.getConstructor(Class.java:531)
        at java.lang.Class.getDeclaredConstructor(Class.java:510)
        at java.lang.Class.newInstance(Class.java:1561)
            at android.support.v4.app.Fragment.instantiate(Fragment.java:420)
            at android.support.v4.app.FragmentState.instantiate(Fragment.java:101)
            at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1833)
            at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:264)
            at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:122)
            at com.package.appname.Frontpage.onCreate(Frontpage.java:68)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3912)
            at android.app.ActivityThread.access$900(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Solution

  • Create an interface like this

    public interface NameChangedListener {
        void nameChanged(String name);
    }
    

    Add the following code to your MainActvity

    private WeakHashMap<NameChangedListener, String> nameChangedListenerHashMap;
    
        public void addNameChangedListener(
                NameChangedListener nameChangedListener) {
            if (nameChangedListenerHashMap == null) {
                nameChangedListenerHashMap = new WeakHashMap<NameChangedListener, String>();
            }
            nameChangedListenerHashMap.put(nameChangedListener,
                    "entry");
        }
    
        private void fireNameChange() {
            if (nameChangedListenerHashMap != null) {
                Iterator<NameChangedListener> iterator = nameChangedListenerHashMap
                        .keySet().iterator();
                while (iterator.hasNext()) {
                    NameChangedListener nameChangedListener = iterator.next();
                    if (nameChangedListener != null) {
                        SharedPreferences pref = PreferenceManager
                                .getDefaultSharedPreferences(this);
                        String name = pref.getString("example_text", "");
                        nameChangedListener.nameChanged(name);
                    }
                }
            }
        }
    
        @Override
        protected void onResume() {
            // TODO Auto-generated method stub
            super.onResume();
            fireNameChange();
        }
    

    Edit your Fragment

    public class PlaceholderFragment extends Fragment implements NameChangedListener{
    
        private TextView textView;
    
        private String previousName = null;
    
        public PlaceholderFragment() {
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
    
            LayoutInflater lf = getActivity().getLayoutInflater();
            View rootView = lf.inflate(R.layout.fragment_frontpage, container,
                    false);
            SharedPreferences pref = PreferenceManager
                    .getDefaultSharedPreferences(getActivity());
            previousName = pref.getString("example_text", "");
            textView = (TextView) rootView.findViewById(R.id.NameView);
            textView.setText(previousName);
            return rootView;
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            ((MainActivity)activity).addNameChangedListener(this);
        }
    
        @Override
        public void nameChanged(String name) {
            // TODO Auto-generated method stub
            if (!name.equals(previousName)) {
                textView.setText(name);
                previousName = name;
            }
        }
    
    }
    

    Refer : http://simpledeveloper.com/how-to-communicate-between-fragments-and-activities/