gpt4 book ai didi

android - 使用数据绑定(bind)将数据从 viewModel 传递到 onClick 函数的正确方法是什么?

转载 作者:行者123 更新时间:2023-11-30 04:59:31 25 4
gpt4 key购买 nike

我正在尝试将 LiveData 对象作为一些数据绑定(bind)函数参数传递,但我不断得到 null 值。我尝试在我的 fragment 中使用 viewmodel.getTrainingActivity.observe()... 方法获取该值并且它有效,所以它必须链接到实时数据生命周期,但我无法解决这个问题。
传递我提到的数据的正确方法是什么?

我的 onClick 方法:

android:onClick="@{() -> presenter.showSelectActivityDialog(viewmodel.trainingActivity)}"

我的演示者方法:

public void showSelectActivityDialog(TrainingActivity trainingActivity){
Log.i(TAG, "Training activity: " + trainingActivity.getName());
}

我的 viemodel 类:

public class TrainingFragmentViewModel extends ViewModel {
public final static String TAG = TrainingFragmentViewModel.class.getSimpleName();
private MediatorLiveData<TrainingStatus> status = new MediatorLiveData<>();
private MediatorLiveData<String> time = new MediatorLiveData<>();
private MediatorLiveData<String> distance = new MediatorLiveData<>();
private MediatorLiveData<String> speed = new MediatorLiveData<>();
private MediatorLiveData<String> calories = new MediatorLiveData();
private MediatorLiveData<String> objective = new MediatorLiveData();
private TrainingFragmentRepository trainingFragmentRepository;

public TrainingFragmentViewModel(TrainingFragmentRepository repository) {
Log.i(TAG, "VIEW MODEL CREATED");
this.trainingFragmentRepository = repository;
status.addSource(repository.getStatus(), status::setValue);
time.addSource(repository.getTime(), time::setValue);
distance.addSource(repository.getDistance(), distance::setValue);
speed.addSource(repository.getDistance(), speed::setValue);
calories.addSource(repository.getCalories(), calories::setValue);
objective.addSource(repository.getObjective(), calories::setValue);
}

public LiveData<TrainingStatus> getStatus() {
return status;
}

public MediatorLiveData<String> getTime() {
return time;
}

public MediatorLiveData<String> getDistance() {
return distance;
}

public MediatorLiveData<String> getSpeed() {
return speed;
}

public MediatorLiveData<String> getCalories() {
return calories;
}

public MediatorLiveData getObjective() {
return objective;
}

public LiveData<List<TrainingActivity>> getTrainingActivities() {
return trainingFragmentRepository.getAllTrainingActivities();
}

public LiveData<TrainingActivity> getTrainingActivity() {
return trainingFragmentRepository.getTrainingActivity();
}

public static class Factory extends ViewModelProvider.NewInstanceFactory {
private final TrainingFragmentRepository repository;

public Factory(TrainingFragmentRepository repository) {
this.repository = repository;

}

@SuppressWarnings("unchecked")
@NonNull
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return (T) new TrainingFragmentViewModel(repository);
}

}

}


完整的 xml 文件:

<layout  xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:bind="http://schemas.android.com/apk/res-auto">

<data>

<import type="android.view.View" />
<import type=".features.training.TrainingStatus" />
<variable
name="viewmodel"
type=".fragments.training.main_training.TrainingFragmentViewModel" />

<variable
name="presenter"
type=".fragments.training.main_training.TrainingFragmentPresenter" />

</data>


<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.training.main_training.TrainingFragment">

<fragment
android:id="@+id/fragmentTrainingWithMap"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:name=".fragments.training.trainingMap.googleMap.TrainingGoogleMapFragment"/>

<include
android:id="@+id/include3"
layout="@layout/fragment_training_top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/main_training_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include3">


<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
app:layout_behavior=".fragments.training.main_training.BlockableAppBarLayoutBehaviour">


<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/training_collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="370dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
app:layout_scrollFlags="exitUntilCollapsed|scroll|snap">


<FrameLayout
android:id="@+id/fragment_training_distance_and_activity_bar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_gravity="top"
android:layout_marginTop="220dp">

<LinearLayout
android:id="@+id/fragment_training_layout_distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:orientation="vertical"
app:layout_collapseMode="none">

<TextView
android:id="@+id/textView28"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DYSTANS km"
android:textAppearance="@style/TextAppearance.MyTheme.Subtitle1" />

<TextView
android:id="@+id/fragment_training_distance_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/stoltz_book"
android:text='@{viewmodel.distance ?? "00,00", default = "00,00"}'
android:textAppearance="@style/TextAppearance.MyTheme.Headline4"
android:textColor="@color/colorPrimary" />
</LinearLayout>

<ImageButton
android:id="@+id/imageButton7"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="bottom|right"
android:background="#00FFFFFF"
bind:srcCompat="@drawable/ic_bieg_w_kole"
android:onClick="@{() -> presenter.showSelectActivityDialog(viewmodel.trainingActivity)}"/>

</FrameLayout>
<!-- android:onClick="@{() -> presenter.showSelectActivityDialog(viewmodel.trainingActivity)}"-->
<FrameLayout
android:id="@+id/fragment_training_add_stage_layout"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="top|left"
android:layout_marginLeft="20dp"
android:layout_marginTop="115dp"
android:layout_marginBottom="60dp"
android:visibility="@{viewmodel.status == TrainingStatus.PAUSED ? View.VISIBLE : View.GONE}">

<ImageButton
android:id="@+id/fragment_training_add_stage_imagebutton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FFFFFF"
android:scaleType="fitXY"
android:src="@drawable/ic_dodaj_etap"
app:layout_collapseMode="none" />
</FrameLayout>


<FrameLayout
android:id="@+id/fragment_training_stop_layout"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="right|top"
android:layout_marginTop="115dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="60dp"
android:visibility="@{viewmodel.status == TrainingStatus.PAUSED ? View.VISIBLE : View.GONE}">

<ImageButton
android:id="@+id/fragment_training_stop_trainig_imagebutton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FFFFFF"
android:onClick="@{() -> presenter.onStopButtonClick()}"
android:scaleType="fitXY"
android:src="@drawable/ic_zakoncz_btn"
app:layout_collapseMode="none" />

</FrameLayout>


<LinearLayout
android:id="@+id/fragment_training_layout_tempo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|top"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:gravity="right"
android:orientation="vertical"
app:layout_collapseMode="pin">

<TextView
android:id="@+id/textView23"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TEMPO min./km"
android:textAppearance="@style/TextAppearance.MyTheme.Subtitle1" />

<TextView
android:id="@+id/fragment_training_tempo_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text='@{viewmodel.speed ?? "00:00", default = "00:00"}'
android:textAppearance="@style/TextAppearance.MyTheme.Headline6" />
</LinearLayout>

<LinearLayout
android:id="@+id/fragment_trainig_start_trainig_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:layout_marginTop="70dp"
android:layout_marginBottom="60dp"
android:gravity="center"
android:orientation="vertical"
app:layout_collapseMode="parallax">


<FrameLayout
android:layout_width="140dp"
android:layout_height="140dp">

<include
layout="@layout/start_stop_button_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:presenter="@{presenter}"
bind:viewmodel="@{viewmodel}" />

</FrameLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:visibility="visible">

<TextView
android:id="@+id/textView26"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:gravity="center"
android:text="CEL:"
android:textAppearance="@style/TextAppearance.MyTheme.Subtitle1" />

<TextView
android:id="@+id/textView27"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:text='@{viewmodel.objective == null ? "0" : viewmodel.objective, default = "0"}'
android:textAppearance="@style/TextAppearance.MyTheme.Body2" />

<TextView
android:id="@+id/textView30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="km"
android:textAppearance="@style/TextAppearance.MyTheme.Caption" />
</LinearLayout>

</LinearLayout>

<LinearLayout
android:id="@+id/fragment_training_layout_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|left"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:orientation="vertical"
app:layout_collapseMode="pin">

<TextView
android:id="@+id/timerLabel2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="CZAS TRWANIA"
android:textAppearance="@style/TextAppearance.MyTheme.Subtitle1" />

<TextView
android:id="@+id/fragment_training_timer_value_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{viewmodel.time ?? "00:00:00", default = "00:00:00"}'
android:textAppearance="@style/TextAppearance.MyTheme.Headline6" />

</LinearLayout>

<include
android:id="@+id/fragment_training_layout_bottom_bar"
layout="@layout/fragment_training_bottom_bar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_gravity="bottom"
bind:presenter="@{presenter}"
bind:viewmodel="@{viewmodel}" />

<include
android:id="@+id/fragment_training_layout_bottom_bar2"
layout="@layout/fragment_training_bottom_bar_2"
android:layout_width="wrap_content"
android:layout_height="70dp"
android:layout_gravity="bottom"
android:visibility="invisible"
bind:viewmodel="@{viewmodel}" />

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/profile_toolbar"
android:layout_width="match_parent"
android:layout_height="70dp"></com.google.android.material.appbar.MaterialToolbar>

<View
android:id="@+id/view5"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="300dp"
android:background="@color/greyedTextColor"
bind:layout_constraintEnd_toEndOf="parent"
bind:layout_constraintStart_toStartOf="parent"
bind:layout_constraintTop_toBottomOf="@+id/imageView8" />

<include
android:id="@+id/fragment_training_details_bar"
layout="@layout/fragment_training_details_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:visibility="gone" />


</com.google.android.material.appbar.CollapsingToolbarLayout>

</com.google.android.material.appbar.AppBarLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/fragment_training_map_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingLeft="10dp"
android:paddingTop="8dp"
android:paddingRight="10dp"
android:paddingBottom="8dp"
bind:layout_anchor="@id/appBarLayout"
bind:layout_anchorGravity="bottom">


<ImageButton
android:id="@+id/imageButton3"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#00FFFFFF"
android:scaleType="fitXY"
bind:layout_constraintBottom_toBottomOf="parent"
bind:layout_constraintEnd_toEndOf="parent"
bind:layout_constraintTop_toTopOf="parent"
bind:srcCompat="@drawable/ic_map_wysrodkuj" />

<ImageButton
android:id="@+id/imageButton5"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="8dp"
android:background="@drawable/map_satellite"
android:scaleType="fitXY"
bind:layout_constraintBottom_toBottomOf="parent"
bind:layout_constraintEnd_toStartOf="@+id/imageButton3"
bind:layout_constraintTop_toTopOf="parent" />

<ImageButton
android:id="@+id/imageButton6"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#00FFFFFF"
android:scaleType="fitXY"
android:src="@drawable/ic_map_aparat_btn"
app:layout_constraintStart_toStartOf="parent"
bind:layout_constraintBottom_toBottomOf="parent"
bind:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

<FrameLayout
android:id="@+id/start_stop_on_map_layout"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_marginBottom="32dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/fragmentTrainingWithMap"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">

<FrameLayout
android:id="@+id/start_stop_on_map_layout_to_animate"
android:layout_width="match_parent"
android:layout_height="match_parent">

<include
layout="@layout/start_stop_button_layout"
android:layout_width="110dp"
android:layout_height="110dp"
android:background="#00FFFFFF"
bind:presenter="@{presenter}"
bind:viewmodel="@{viewmodel}" />
</FrameLayout>

</FrameLayout>



</androidx.constraintlayout.widget.ConstraintLayout>

</layout>

最佳答案

为什么要分离 Presenter 和 View Model?按MVVM 概念presenter 应该是ViewModel。

所以 showSelectActivityDialog 应该是 ViewModel 的一部分,并且应该直接获取值 getTrainingActivity().getValue()

此外,请记住,使用 MVVM 超车并不是一件好事,请考虑使用新的 Navigation arch 组件或仅在 Activity/Fragment 中以旧方式管理 UI 流

关于android - 使用数据绑定(bind)将数据从 viewModel 传递到 onClick 函数的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58482190/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com