# SharedViewModel Between Fragments ###### tags: `Android` `SharedViewModel` `ViewModel` [TOC] **ViewModel Introduction** In order to use ViewModel you **MUST** implement arch lifecycle in order to use it. For more information check Android Developer Website: https://developer.android.com/jetpack/androidx/releases/lifecycle ```java= //ViewModel implementation 'android.arch.lifecycle:extensions:1.1.1' ``` ## SharedViewModel between Fragments ### Introduction We will have two fragments sharing same viewModel. So if there is an update in the information used by both, both will update automatically. ### Note FYI: We used **viewBinding** for layout. To enable it, go to gradle to open this function. ```java=== //build.gradle(app) viewBinding { enabled = true } ``` ## Coding Part We will have 2 XML(1 for Activity and 1 for Fragment) and 3 class (1 Activity, 1 Fragment and 1 Class extending ViewModel). ### Class Section >**Class**[color=#187fce] **SharedVM.java** ```java=== package com.studyappjava; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; public class SharedVM extends ViewModel { private MutableLiveData<CharSequence> textDisplay = new MutableLiveData<>(); public void setTextDisplay(CharSequence input){ textDisplay.setValue(input); } public LiveData<CharSequence> getTextDisplay(){ return textDisplay; } } ``` **SharedVMActivity.java** ```java=== package com.studyappjava; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import com.studyappjava.databinding.ActivitySharedVmBinding; import com.studyappjava.fragment.FragmentA; public class SharedVMActivity extends AppCompatActivity { private ActivitySharedVmBinding dealBind; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initFragments(); } private void initView(){ View dealView = LayoutInflater.from(this).inflate(R.layout.activity_shared_vm, null); dealBind = ActivitySharedVmBinding.bind(dealView); setContentView(dealBind.getRoot()); } private void initFragments(){ getSupportFragmentManager().beginTransaction() .add(R.id.fr_a_container, new FragmentA()) .add(R.id.fr_b_container, new FragmentA()) .commit(); } } ``` **FragmentA.java** >**Note**: > We use: > :heavy_check_mark: **dealVM.getTextDisplay().observe(getViewLifecycleOwner(), new Observer)** > :X:**dealVM.getTextDisplay().observe(this, new Observer)** [color=red] > **Reason:** > **this** refers to **Fragment**, that means we scope the live data to the lifecycle of the fragment instance. This means that the observer get removed only when the progress goes through onDestroy fragment. >However, observer is added in onActivityCreated, this means that if we go through onDestroyView and onCreateView, many observers will be created. Therefore, we use **getViewLifecycleOwner()** which will scope to fragment's view lifecycle instead. [color=pink] >Check [Fragment LifeCycle](/3uK8HoQpT_elQeJzn20Nuw) if needed ```java=== package com.studyappjava.fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; import com.studyappjava.R; import com.studyappjava.SharedVM; import com.studyappjava.databinding.FragmentABinding; public class FragmentA extends Fragment { private SharedVM dealVM; private FragmentABinding dealBind; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_a, container, false); dealBind = FragmentABinding.bind(v); initListener(); return dealBind.getRoot(); } private void initListener(){ dealBind.btnOk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dealVM.setTextDisplay(dealBind.etInput.getText()); } }); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if(getActivity() == null){ return; } dealVM = ViewModelProviders.of(getActivity()).get(SharedVM.class); dealVM.getTextDisplay().observe(getViewLifecycleOwner(), new Observer<CharSequence>() { @Override public void onChanged(CharSequence charSequence) { dealBind.etInput.setText(charSequence); } }); } } ``` ### XML Section >**XML**[color=#187fce] **activity_shared_vm.xml** ```java=== <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SharedVMActivity" android:orientation="vertical"> <FrameLayout android:id="@+id/fr_a_container" android:layout_width="match_parent" android:layout_height="wrap_content"/> <FrameLayout android:id="@+id/fr_b_container" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> ``` **fragment_a.xml** ```java=== <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:gravity="center_horizontal" android:background="@android:color/holo_blue_light" android:orientation="vertical"> <EditText android:id="@+id/et_input" android:layout_width="match_parent" android:layout_height="wrap_content"/> <Button android:id="@+id/btn_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@android:string/ok"/> </LinearLayout> ```