Skip to content

Instantly share code, notes, and snippets.

@shashankdaima
Last active February 9, 2023 22:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shashankdaima/6261ec8fd30bf49cd011ac4a5ca7aa27 to your computer and use it in GitHub Desktop.
Save shashankdaima/6261ec8fd30bf49cd011ac4a5ca7aa27 to your computer and use it in GitHub Desktop.

Motivation to use simple stack :

  1. Instance State Restoration
  2. Navigation b/w fragment or views in so-called navigation components way.
  3. Basic viewmodels should be attached to fragment/view that has lifecycle of activity-retained scope.
  4. Service locator/DI for simple apps that works at Singleton Component and ActivityRetainedComponent.
  5. [Pro-point] You can control your navigator from viewModel, so no more dependence on channelFlow for such basic action.

How To Use that in current App:

  1. Make a new Activity[SimpleStackMainActivity.java].
 class SimpleStackMainActivity extends AppCompatActivity{
 
   onCreate(){
       DefaultFragmentStateChanger fragmentStateChanger = new DefaultFragmentStateChanger(getSupportFragmentManager(), R.id.container);
       Navigator.configure().setStateChanger(new SimpleStateChanger(this)).setScopedServices(new DefaultServiceProvider()).install(this, binding.container, History.single(HomeKey.create()));
   }
 
 }

Important Note: History.single(HomeKey.create()) is actually clearing up the backstack and HomeKey class as First Navigation Destination for more look at setHistory api(s).

  1. Make your BaseApplication.java like :
class MyApplication extends Application{
  private GlobalServices globalServices;
  
  onCreate(){
    //Defines a singleton components with singleton dependencies. This is maindatory for to run scoped services, which we will be using for lightweight viewModel.
    globalServices = GlobalServices.builder().addService("RecordDatabase", RecordDatabase.getInstance(sApplication)).build();
  }

}
  1. Adding Fragment to the activity having FrameLayout or FragmentContainerView(ig...)

a. Fragment Key

@AutoValue
public abstract class HomeKey extends FragmentKey {
  public static HomeKey create() {
      //This should be generated by AutoValue.. If not, rebuild your project. 
      return new AutoValue_HomeKey();
  }

  @StringRes
  @Override
  public int getTitle() {
      return R.string.app_name;
  }

  @NonNull
  @Override
  protected Fragment instantiateFragment() {
      //Create a single instance of fragment, simple stack will inflate it.
      return new HomeFragment();
  }

  @Override
  public void bindServices(@NonNull ServiceBinder serviceBinder) {
      //Just leave this line if you don't want to use viewModel.
      serviceBinder.addService(HomeViewModel.class.toString(), new HomeViewModel()); 
  }
}

b. Fragment class

@AndroidEntryPoint //You can use hilt for field injection in normal way...
public class HomeFragment extends KeyedFragment {
  private static String TAG = "HomeFragment";
  @Inject
  FirebaseAuth auth;

  public HomeFragment() {
      super(R.layout.activity_main);
  }

  @SuppressLint("SetTextI18n")
  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
      super.onViewCreated(view, savedInstanceState);
      binding = ActivityMainBinding.bind(view);

  }
}

c. ViewModel(via Scoped Service)

public class HomeViewModel implements  ScopedServices.Activated {
    private static String TAG = "HomeViewModel";
    private final MutableLiveData<ViewModelState> _states = new MutableLiveData<>();
    public final LiveData<ViewModelState> state = _states;
    
    //This function will be called when the viewModel will start
    @Override
    public void onServiceActive() {
        _states.postValue(new ViewModelState.Loading());
        HomeViewModelEntryPoint entryPoint = EntryPoints.get(getContext(), HomeViewModelEntryPoint.class);
        auth = entryPoint.getAuth();
    }
    
    //This function will be called when the viewModel will end
    @Override
    public void onServiceInactive() {
        reg.remove();
    } 
    
    //To Use hilt in scoped service you need to make new entry points
    @InstallIn(SingletonComponent.class)
    @EntryPoint
    interface HomeViewModelEntryPoint {
        FirebaseAuth getAuth();
    }


}

Moving from one Fragment To Other Fragment.

Navigator.getBackstack(requireContext()).goTo(RecordKey.create());

Going Back

Navigator.getBackstack(requireContext()).goBack();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment