nakamura johnielo
nakamura johnielo

Reputation: 31

How to Call ViewModelProvider without ref in Flutter

What I Want to Achieve:

I want the search results to be updated every time a character is inputted (or changed) in the search box. I aim to implement this feature as close to clean architecture as possible.

I Use: flutter / flutter-riverpod / get_it

Assumptions:

It's peculiar that a ViewModel is calling another ViewModel within itself. However, I thought this flow was okey when using data binding and trying to implement clean architecture. If my assumptions are incorrect, please point it out.

Sample Code

I want to write the following code but,

Since I am using provider, I need to pass ref from the controller to the presenter to call the viewmodel. This causes unrelated layers to depend on flutter_riverpod and leads to an increase in unnecessary passing of ref. This is causing issues for me.


final searchViewModelProvider =
    ChangeNotifierProvider((ref) => DI<SearchViewModel>());

class SearchViewModel extends ChangeNotifier {
  final ExploreController _exploreController;
  SearchViewModel(this._exploreController);

  List<MyResult> _filteredItems = [];
  String _query = "";

  String get query => _query;
  set query(String value) {
    _query = value;
    _fireController();
    notifyListeners();
  }

  List<MyResult> get filteredItems => _filteredItems;
  set filteredItems(List<MyResult> values) {
    _filteredItems = values;
    notifyListeners();
  }

  Future<void> _fireController() async {
    if (_query.isNotEmpty) {
      _exploreController.search(_query);
    }
  }
}


//controller
//flutter/material.dart have searchcontroller class
class ExploreController {
  SearchInteractor _searchInteractor;
  ExploreController(this._searchInteractor);

  void search(String query) {
    _searchInteractor.execute(query);
  }
}




//usecase
class SearchInteractor {
  MyRepository _myRepository ;
  SearchPresenter _presenter;
  SearchInteractor(this._myRepository,this._presenter);

  void execute(String input) async{
    List<MyResult> results=await _myRepository.getMyResults(input);
    _presenter.execute(results);
  }
}


//presenter
class SearchPresenter {
  SearchViewModel _viewModel ;
  SearchPresenter(this._viewModel);

  void execute(List<MyResult> input) async{
    _viewModel.filteredItems=input;
  }
}

final DI = GetIt.instance;

void setupLocator() {

  //repository
  DI.registerSingleton<MyRepository>(() => MyRepository());

  //viewmodel
  DI.registerFactory<SearchViewModel>(
      () => SearchViewModel(DI<ExploreController>()));
     
  //controller
  DI.registerFactory<ExploreController>(
      () => ExploreController(DI<SearchInteractor>())); 

  //usecase
  DI.registerFactory<SearchInteractor>(() => SearchInteractor(
      DI<MyRepository>(), DI<SearchPresenter>()));

  //presenter
  DI.registerFactory<SearchPresenter>(() => SearchPresenter());
}

Upvotes: 0

Views: 32

Answers (0)

Related Questions