考虑一个与viewModel数据绑定的布局。更具体地说,布局使用布局变量来访问底层的viewModel。每当绑定被填充时,它的viewModel和lifeCycleOwner都将被设置。(当然,viewModel包含一些liveData,直接绑定到某些视图属性)。
一个RecyclerView(在Activity中创建并设置)传递了一个viewModel列表。对于每个viewModel,通过填充新的布局副本和其数据绑定来创建ViewHolder。
onBindViewHolder策略是:
- 不触及viewModels - 设置ViewHolder.dataBinding.setViewModel(viewModels[position])
但是如何设置LifeCycleOwner?
将LifeCycleOwner作为参数传递给Adapter可以吗?毕竟,适配器只会像RecyclerView一样存在,而后者只会在父Activity存在期间保持活动状态。
在RecyclerView的上下文中使用dataBinding是否是合理的方法?
fig1. layout_counter.xml:添加到RecyclerView的单个组件的布局。
一个RecyclerView(在Activity中创建并设置)传递了一个viewModel列表。对于每个viewModel,通过填充新的布局副本和其数据绑定来创建ViewHolder。
onBindViewHolder策略是:
- 不触及viewModels - 设置ViewHolder.dataBinding.setViewModel(viewModels[position])
但是如何设置LifeCycleOwner?
将LifeCycleOwner作为参数传递给Adapter可以吗?毕竟,适配器只会像RecyclerView一样存在,而后者只会在父Activity存在期间保持活动状态。
在RecyclerView的上下文中使用dataBinding是否是合理的方法?
fig1. layout_counter.xml:添加到RecyclerView的单个组件的布局。
代码(如有必要)
- MainViewModel.java
- Adapter.java
- MainActivity.java
- layout_counter.xml
- layout_main.xml
MainViewModel.java
package com.gmail.example.rough;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
public class MainViewModel extends androidx.lifecycle.ViewModel {
private MutableLiveData<String> date, time, name;
public MainViewModel() {
this.date = new MutableLiveData<>(LocalDateTime.now().toString());
this.time = new MutableLiveData<>(LocalTime.now().toString());
this.name = new MutableLiveData<>(UUID.randomUUID().toString().substring(0,10));
Timer t=new Timer();
t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
date.postValue(LocalDateTime.now().toString());
time.postValue(LocalTime.now().toString());
}
}, 0, 1000);
}
public LiveData<String> getDate() {
return date;
}
public LiveData<String> getTime() {
return time;
}
public LiveData<String> getName() {
return name;
}
}
Adapter.java
package com.gmail.example.rough;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.gmail.example.rough.databinding.LayoutCounterBinding;
import java.util.List;
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
private LayoutCounterBinding binding;
public ViewHolder(@NonNull View itemView, LayoutCounterBinding binding) {
super(itemView);
this.binding = binding;
}
public LayoutCounterBinding getBinding() {
return binding;
}
}
List<MainViewModel> vms;
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.layout_counter, parent, false);
LayoutCounterBinding binding = DataBindingUtil.inflate(inflater, R.layout.layout_counter, parent, false);
return new ViewHolder(view, binding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.getBinding().setVm(vms.get(position));
//how to set the LifeCycleOwner?
// holder.getBinding().setLifecycleOwner(???);
}
@Override
public int getItemCount() {
return vms.size();
}
public Adapter(List<MainViewModel> vms) {
this.vms = vms;
}
}
MainActivity.java
package com.gmail.example.rough;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.os.Bundle;
import com.gmail.example.rough.databinding.LayoutMainBinding;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
LayoutMainBinding binding = LayoutMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
ArrayList<MainViewModel> vms = new ArrayList<>();
vms.add(new MainViewModel());
vms.add(new MainViewModel());
vms.add(new MainViewModel());
binding.recyclerView.setAdapter(new Adapter(vms));
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
layout_counter.xml
<?xml version="1.0" encoding="utf-8"?>
<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">
<data>
<variable
name="vm"
type="com.gmail.example.rough.MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".logger.android.MainActivity">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="19dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="@{vm.name}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/layoutRealtive"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvName">
<TextView
android:id="@+id/tvTs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@id/tvTime"
android:layout_alignTop="@id/tvTime"
android:text="@{vm.date}" />
<TextView
android:id="@+id/tvTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:gravity="center"
android:textAlignment="center"
android:textSize="36sp"
android:textStyle="bold"
/>
<ImageView
android:id="@+id/ivReset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/tvTime"
android:layout_alignBottom="@id/tvTime"
android:layout_alignParentEnd="true"
android:src="@drawable/ic_launcher_foreground"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
layout_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="409dp"
android:layout_height="729dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>