Model-View-ViewModel (MVVM)

One Activity, one view

One Activity holds one view (Fragment) and ViewModel. I want to retain the ViewModel instance when the screen is rotated, but create the new one when backs from the other Activity.

  • MainActivity

    public class MainActivity extends AppCompatActivity {
    
      private static final String MAIN_VIEWMODEL_TAG = "MAIN_VIEWMODEL_TAG";
    
      @Inject
      Lazy<MainViewModel> viewModelProvider;
    
      @Inject
      Lazy<MainFragment> fragmentProvider;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findOrCreateViewThenDisplayIt(findOrCreateViewModel(MAIN_VIEWMODEL_TAG));
      }
    
      private void findOrCreateViewThenDisplayIt(@NonNull MainViewModel viewModel) {
        BaseView<MainViewModel> baseView = findView();
        if (baseView == null) {
          baseView = fragmentProvider.get();
          baseView.setViewModel(viewModel);
          ActivityUtils.addFragmentToActivity(
              getSupportFragmentManager(), baseView, R.id.contentFrame);
        } else {
          baseView.setViewModel(viewModel);
        }
      }
    
      @SuppressWarnings("unchecked")
      @Nullable
      private BaseView<MainViewModel> findView() {
        return (BaseView<MainViewModel>) getSupportFragmentManager()
            .findFragmentById(R.id.contentFrame);
      }
    
      @NonNull
      private MainViewModel findOrCreateViewModel(@NonNull String tag) {
        // In a configuration change we might have a ViewModel present. It's retained using the
        // Fragment Manager.
        @SuppressWarnings("unchecked")
        ViewModelHolder<MainViewModel> retainedViewModel =
            (ViewModelHolder<MainViewModel>) getSupportFragmentManager().findFragmentByTag(tag);
    
        if (retainedViewModel != null && retainedViewModel.getViewmodel() != null) {
          // If the model was retained, return it.
          return retainedViewModel.getViewmodel();
        } else {
          // There is no ViewModel yet, create it.
          MainViewModel viewModel = viewModelProvider.get();
          // and bind it to this Activity's lifecycle using the Fragment Manager.
          ActivityUtils.addFragmentToActivity(
              getSupportFragmentManager(),
              ViewModelHolder.createContainer(viewModel),
              tag);
          return viewModel;
        }
      }
    }
    
  • MainViewModel

    @ActivityScoped
    public class MainViewModel extends BaseObservable implements BaseViewModel {
    
      @Inject
      MainViewModel() {
    
      }
    }
    

    Should set its scope same as Activity.

  • MainFragment

    @ActivityScoped
    public class MainFragment extends BaseView<MainViewModel> {
    
      @Inject
      public MainFragment() {
        // Required empty public constructor
      }
    
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
          Bundle savedInstanceState) {
        FragmentMainBinding binding = DataBindingUtil
            .inflate(inflater, R.layout.fragment_main, container, false);
        binding.setViewModel(viewModel);
        return binding.getRoot();
      }
    }
    
  • LogCat

    I/main: onCreate()
    D/main: get ViewModel from Dagger!
    I/MainViewModel: MainViewModel()
    D/main: viewModel is com.hsy.d.main.MainViewModel@96bf940
    D/main: get View from Dagger!
    I/MainFragment: MainFragment()
    I/MainFragment: onCreate()
    I/MainFragment: onCreateView()
    I/main: onStart()
    D/MainFragment: onResume(): viewModel is com.hsy.d.main.MainViewModel@96bf940
    
    // rotation
    I/main: onStop()
    I/MainFragment: onDestroy()
    I/main: onDestroy()
    
    I/main: onCreate()
    I/MainFragment: MainFragment()
    I/MainFragment: onCreate()
    D/main: ViewModel was retained
    D/main: viewModel is com.hsy.d.main.MainViewModel@96bf940
    D/main: View was retained
    I/MainFragment: onCreateView()
    I/main: onStart()
    D/MainFragment: onResume(): viewModel is com.hsy.d.main.MainViewModel@96bf940
    
    // start other Activity and finish self
    I/main: onStop()
    I/MainFragment: onDestroy()
    I/main: onDestroy()
    
    // back to MainActivity
    I/main: onCreate()
    D/main: get ViewModel from Dagger!
    I/MainViewModel: MainViewModel()
    D/main: viewModel is com.hsy.d.main.MainViewModel@696feeb
    D/main: get View from Dagger!
    I/MainFragment: MainFragment()
    I/MainFragment: onCreate()
    I/MainFragment: onCreateView()
    I/main: onStart()
    D/MainFragment: onResume(): viewModel is com.hsy.d.main.MainViewModel@696feeb
    

android-architecture MVVM

results matching ""

    No results matching ""