I want to call a Method from my ViewModel
Class with onClick()
,
but the call is just not executed. DataBinding is working fine otherwise.
android:onClick="@{() -> ViewModel.test()}"
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/androidxmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="Project"
type="de.umr.studipro3000.model.Project" />
<variable
name="ViewModel"
type="de.umr.studipro3000.viewmodel.ProjectOverviewViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:onClick="@{() -> ViewModel.test()}"
android:padding="8dp">
<TextView
android:id="@+id/text_view_projectName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Project.name}"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</RelativeLayout>
</layout>
Strange thing is, this is executed just fine.
android:onClick="@{() -> System.out.println(Project.name)}"
<data>
<variable
name="Project"
type="de.umr.studipro3000.model.Project" />
<variable
name="ViewModel"
type="de.umr.studipro3000.viewmodel.ProjectOverviewViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:onClick="@{() -> System.out.println(Project.name)}"
android:padding="8dp">
<TextView
android:id="@+id/text_view_projectName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Project.name}"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</RelativeLayout>
This is the ViewModel:
public class ProjectOverviewViewModel extends ViewModel {
private Repository repository;
private AuthService authService;
private MutableLiveData<List<Project>> projectsLiveData;
private String errorMessage;
private ProjectOverViewNavigator navigator;
public void setNavigator(ProjectOverViewNavigator navigator) {
this.navigator = navigator;
}
public ProjectOverviewViewModel() {
this.repository = Repository.getInstance();
this.authService = AuthService.getInstance();
this.errorMessage = "";
projectsLiveData = new MutableLiveData<>();
handleResponse(repository.projects((authService.currentToken.getValue())));
}
private void handleResponse(LiveData<ProjectListResponse> projectListResponseLiveData) {
projectListResponseLiveData.observeForever(
projectListResponse -> {
ProjectListSuccessResponse projectListSuccessResponse =
projectListResponse.getProjectListSuccessResponse();
if (projectListSuccessResponse != null) {
projectsLiveData.setValue(projectListSuccessResponse.getResult());
System.out.println(projectsLiveData.getValue().toString());
} else {
errorMessage = projectListResponse.getErrorResponse().getError();
}
});
}
public void itemClick(Project project) {
System.out.println("CLICKED");
navigator.onItemClick(project);
}
public void test(){
System.out.println("TEST");
}
public MutableLiveData<List<Project>> getProjectsLiveData() {
return projectsLiveData;
}
public void setProjectsLiveData(MutableLiveData<List<Project>> projectsLiveData) {
this.projectsLiveData = projectsLiveData;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
This is my Fragment
public class projectOverviewFragment extends Fragment implements ProjectOverViewNavigator {
private ProjectOverviewViewModel viewModel;
private ProjectAdapter adapter;
private FragmentProjectOverviewBinding binding;
private NavController navController;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(ProjectOverviewViewModel.class);
viewModel.setNavigator(this);
adapter = new ProjectAdapter();
}
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
binding = FragmentProjectOverviewBinding.inflate(inflater, container, false);
binding.setProjectOverviewViewModel(viewModel);
binding.setLifecycleOwner(this);
RecyclerView recyclerView = binding.recyclerViewProjects;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(adapter);
binding.getProjectOverviewViewModel().test();
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
navController = Navigation.findNavController(view);
viewModel
.getProjectsLiveData()
.observe(getViewLifecycleOwner(), projects -> adapter.setProjects(projects));
}
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.setting_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
/*case R.id.first_action:
// your first action code
return true;
case R.id.second_action:
// your second action code
*/
return true;
}
@Override
public void onItemClick(Project project) {
System.out.println(project.getDescription());
/* projectOverviewFragmentDirections.ActionProjectOverviewFragmentToProjectDetailsFragment action =
projectOverviewFragmentDirections.actionProjectOverviewFragmentToProjectDetailsFragment(
project.getId());
navController.navigate(action);*/
}
}
I had to do the Databinding of the Viewmodel for the individual Listitem in the Project Adapter. The VieModel of the ProjectAdapter is set in the Fragment.
public class ProjectAdapter extends RecyclerView.Adapter<ProjectAdapter.ProjectViewHolder> {
private ProjectOverviewViewModel viewModel;
public void setProjects(List<Project> projects) {
this.projects = projects;
notifyDataSetChanged();
}
public void setViewModel(ProjectOverviewViewModel viewModel) {
this.viewModel = viewModel;
}
public static class ProjectViewHolder extends RecyclerView.ViewHolder {
private ProjectItemBinding projectItemBinding;
public ProjectViewHolder(@NonNull ProjectItemBinding projectItemBinding) {
super(projectItemBinding.getRoot());
this.projectItemBinding = projectItemBinding;
}
}
private List<Project> projects = new ArrayList<>();
@NonNull
@Override
public ProjectViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ProjectItemBinding projectItemBinding =
DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()), R.layout.project_item, parent, false);
return new ProjectViewHolder(projectItemBinding);
}
@Override
public void onBindViewHolder(@NonNull ProjectViewHolder holder, int position) {
Project currentProject = projects.get(position);
holder.projectItemBinding.setProject(currentProject);
holder.projectItemBinding.setProjectOverviewViewModel(viewModel);
}
@Override
public int getItemCount() {
return projects.size();
}
}
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
binding = FragmentProjectOverviewBinding.inflate(inflater, container, false);
binding.setLifecycleOwner(this);
binding.setProjectOverviewViewModel(viewModel);
RecyclerView recyclerView = binding.recyclerViewProjects;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
adapter.setViewModel(viewModel);
recyclerView.setAdapter(adapter);
return binding.getRoot();
}