Search code examples
androidandroid-fragmentsandroid-lifecycleandroid-livedata

Android LiveData creating multiple observers in fragment


After searching lots of other SO questions and reading articles I'm still stuck as to why my implementation does not seem to perform as other examples.

I've read that it's recommended to use getViewLifecycleOwner() when registering any LiveData observers inside of a fragment to handle the lifecycle of the fragment correctly.

However, inside my fragment OnActivityCreated method (which gets called twice when the fragment is shown on the screen) I seem to get different LifecycleOwner objects from the call to getViewLifecycleOwner() which I beleive is the reason I'm getting multiple observers registered to my LiveData object.

How do I prevent this from happening / what am I doing wrong?

I've added lots of logging to the code as below:

MainActivity

   public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment, new LiveDataTestFragment())
                    .commit();

            Log.d("debugger2", "Activity: " + this.hashCode());
        }
    }

LiveDataTestFragment

public class LiveDataTestFragment extends Fragment {

    private LiveDataViewModel viewModel;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_live_data_test, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        viewModel = ViewModelProviders.of(getActivity()).get(LiveDataViewModel.class);

        Log.d("debugger2", "ViewModel: " + viewModel.hashCode());

        LiveData<String> liveData = viewModel.getLiveData();
        Log.d("debugger2", "LiveData: " + liveData.hashCode());

        LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
        Log.d("debugger2", "LifeCycleOwner: " + lifecycleOwner.hashCode());

        liveData.observe(lifecycleOwner, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.d("debugger2", "observer hash: " + this.hashCode());
            }
        });
    }
}

Logcat:

D: Activity: 242098714
D: ViewModel: 149122972
D: LiveData: 58736037
D: LifeCycleOwner: 50378106
D: ViewModel: 149122972
D: LiveData: 58736037
D: LifeCycleOwner: 245135826
D: observer hash: 204470220
D: observer hash: 226765595

Solution

  • I've figured out the issue. Thanks for the answers regardless!

    I'll put the issue here even though it's unlikely anyone else will do what I did!

    My activity_main.xml contained

    <fragment
        android:name="com.test.livedatatestapp.LiveDataTestFragment"
        android:id="@+id/fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    which was creating an instance of the Fragment class, which I was then immediately replacing inside MainActivity by replacing the Fragment, hence the duplicates...