Pisze drobną aplikacje androidową (jedno activity, 3-4 fragmenty) chciałem na niej nauczyć się MVVM... Męczę się już z tym sporo czasu i sporo przeczytałem. Nie bardzo wiem jak poradzić sobie z przesyłaniem danych między fragmentami i ogólnie zmianą fragmentów tworze w activity interfejs zmieniający fragmenty tylko nie wiem jak go przesłać do view modelu fragmentu. Jeśli tworze własny konstruktor fragmentu wyświetla żeby użyć bundle a przez bundle albo ja nie wiem jak przesłać interfejs albo się nie bardzo da... Proszę o wyrozumiałość i będę wdzięczny za jakiekolwiek porady...

- Rejestracja:około 7 lat
- Ostatnio:prawie 4 lata
- Lokalizacja:Kraków
- Postów:834
Fragmenty mogą mieć tylko bezargumentowe konstruktory. Jeżeli chcesz przekazać jakieś dane typu ID wybranego produktu, to powinny być przekazane, jak zauważyłeś, w Bundle
do metody setArguments
. Obiekt służący do nawigacji, powinien być pobierany np. z Activity w odpowiednim momencie cyklu życia Fragmentu i raczej nie należy go pchać do ViewModelu.
Wklej jakiś minimalny przykład z dwoma Fragmentami, bo inaczej ciężko będzie poradzić coś konkretnego.
- Rejestracja:ponad 7 lat
- Ostatnio:ponad 4 lata
- Postów:13
Michał Sikora napisał(a):
Fragmenty mogą mieć tylko bezargumentowe konstruktory. Jeżeli chcesz przekazać jakieś dane typu ID wybranego produktu, to powinny być przekazane, jak zauważyłeś, w
Bundle
do metodysetArguments
. Obiekt służący do nawigacji, powinien być pobierany np. z Activity w odpowiednim momencie cyklu życia Fragmentu i raczej nie należy go pchać do ViewModelu.Wklej jakiś minimalny przykład z dwoma Fragmentami, bo inaczej ciężko będzie poradzić coś konkretnego.
Kod jest obecnie nieco rozgrzebany przez dziesiątki różnych moich prób i błędów a w zasadzie głównie błędów ale postaram się wydobyć co najważniejsze:
IFragMenager
public interface IFragMenager {
void goMenu();
void goResult(int points);
void goGame();
}
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
goMenu();
}
@Override
public void goMenu() {
MenuFragment newFragment = new MenuFragment ();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame, newFragment);
transaction.commit();
}
@Override
public void goResult(int points) {
//TODO: goResult
}
@Override
public void goGame() {
//TODO:goGame
}
}
MenuFragment
public class MenuFragment extends Fragment{
IFragMenager iFragMenager;
MenuViewModel menuViewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentMenuBinding binding = DataBindingUtil.inflate(inflater,R.layout.fragment_menu,container,false);
View view = binding.getRoot();
ButterKnife.bind(this,view);
//menuViewModel=MenuViewModel.getInstance();
menuViewModel=new MenuViewModel();
binding.setMenuViewModel(menuViewModel);
return view;
}
}
MenuViewModel
public class MenuViewModel extends BaseObservable{
public void onClickGame(View view){
Log.i("ML","GameClick");
}
}
To takei co istotniejsze wycinki kodu mam nadzieje że nic istotnego nie pominąłem... I chodzi mi o to aby przycisk po naciśnięciu którego wykonuje się metoda onClickGame z MenuViewModel powodował zmianę fragmentu na inny w tym przypadku metoda goGame() z interfejsu.

- Rejestracja:około 7 lat
- Ostatnio:prawie 4 lata
- Lokalizacja:Kraków
- Postów:834
Szczerze, to trochę kiepski przykład. ViewModel
powineń służyć, żeby oddzielić logikę domenową od kontrolerów typu Fragment
czy Activity
i nie powinien zawierać referencji do klas androidowych takich jak View
. Nawigacja pomiędzy ekranami należy jak najbardziej do warstwy widoku i tam powinna zostać.
Pomijając to, to w swoim przykładnie musiałbyś zrobić coś w tym stylu.
public class MenuFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle inState) {
FragmentMenuBinding binding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_menu,
parent,
false
);
IFragMenager fragmentManager = (IFragMenager) getActivity();
MenuViewModel menuViewModel = new MenuViewModel(fragmentManager);
binding.setMenuViewModel(menuViewModel);
return binding.getRoot();
}
}
public class MenuViewModel extends BaseObservable {
private final IFragMenager fragmentManager;
public MenuViewModel(IFragMenager fragmentManager) {
this.fragmentManager = fragmentManager;
}
public void onClickGame(View view) {
fragmentManager.goMenu();
}
}
Ponieważ MainActivity
implementuje interfejs IFragMenager
, to musisz pobrać go we fragmencie i zrzutować na ten interfejs. Inaczej się w Twoim przykładzie nie da. Niesie to ze sobą trochę problemów, ale myślę, że w tej chwili nie powinny Cię one obchodzić. Aczkolwiek wydaje mi się, że ten przykład, to bardziej nauka nastawiona na DataBinding
niż ViewModel
.