使用 ViewModel 按 ID 获取项目
Get item by ID using ViewModel
在我的 MainActivity 中,我在适配器中显示了项目。这些项目是房间实体对象。当我单击适配器中的一个项目时,我会启动一个 DetailActivity。
现在,在此 DetailActivity 中,我想使用 ViewModel 和 Entity 对象的 ID 获取点击的项目。
我的问题是,我不确定该怎么做。我应该使用 LiveData 吗?我很困惑,因为像 this Google Codelab 这样的例子总是在 LiveData 中包装 Entity 对象,所以要获取对象本身,你必须观察 onChanged
的变化并使用方法的参数。
我目前的做法是在 MainActivity 中使用 Intent putExtra
将项目的 ID 发送到 DetailActivity:
/** Called when an item in the places list is clicked.
*
* @param view The view displaying place name and address
* @param position The position of the place item
*/
@Override
public void onItemClick(View view, int position) {
// start DetailActivity
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra(EXTRA_PLACE_ID, adapter.getItem(position).getPlaceId());
// get the position that was clicked
// This will be used to save or delete the place from the DetailActivity buttons
clickedPlacePos = position;
startActivityForResult(intent, DETAIL_ACTIVITY_REQUEST_CODE);
}
然后在DetailActivity中,获取ID后,通过ID与ViewModel获取Entity对象:
viewModel = new ViewModelProvider(this).get(PlaceViewModel.class);
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_PLACE_ID)) {
String id = intent.getStringExtra(EXTRA_PLACE_ID);
viewModel.getPlaceById(id).observe(this, new Observer<PlaceModel>() {
@Override
public void onChanged(PlaceModel placeModel) {
// placeModel will be null if place is deleted
if (placeModel != null) {
place = placeModel;
// rest of code using this object is put here
}
}
});
}
这是通过 ID 获取单个项目的常用方法吗?或者有更简单的方法吗?
看起来有点复杂,而且所有使用该对象的代码都必须放在onChanged
中,否则该对象将为空。此外,该代码的上下文将不再是 DetailActivity。我是 Android.
的新手
完整代码为here。
PlaceDao 方法:
@Query("SELECT * FROM place_table WHERE place_id =:id")
LiveData<PlaceModel> getPlaceById(String id);
PlaceRepository 方法:
LiveData<PlaceModel> getPlaceById(String id) {
return placeDao.getPlaceById(id);
}
PlaceViewModel:
import com.michaelhsieh.placetracker.model.PlaceModel;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
public class PlaceViewModel extends AndroidViewModel {
private PlaceRepository repository;
private LiveData<List<PlaceModel>> allPlaces;
public PlaceViewModel(@NonNull Application application) {
super(application);
repository = new PlaceRepository(application);
allPlaces = repository.getAllPlaces();
}
public LiveData<List<PlaceModel>> getAllPlaces() {
return allPlaces;
}
public LiveData<PlaceModel> getPlaceById(String id) {
return repository.getPlaceById(id);
}
public void insert(PlaceModel place) {
repository.insert(place);
}
public void delete(PlaceModel place) {
repository.delete(place);
}
public void update(PlaceModel place) {
repository.update(place);
}
}
Is this the usual approach to get a single item by ID? Or is there a simpler way?
通常的方法是,真正想要的,以 Jetpack 方式做事的现代方式否。但毫不奇怪,Google 没有更新他们的大部分文档,他们也没有更新他们在这方面的大部分示例资源。
无论如何,执行此操作的预期方法是依赖于 SavedStateHandle,并且 Transformations.switchMap。
viewModel = new ViewModelProvider(this).get(PlaceViewModel.class);
// Intent intent = getIntent();
// if (intent.hasExtra(EXTRA_PLACE_ID)) {
// String id = intent.getStringExtra(EXTRA_PLACE_ID);
viewModel.getPlace().observe(this, new Observer<PlaceModel>() {
@Override
public void onChanged(PlaceModel placeModel) {
// placeModel will be null if place is deleted
if (placeModel != null) {
place = placeModel;
// rest of code using this object is put here
}
}
});
和
public class PlaceViewModel extends AndroidViewModel {
private PlaceRepository repository;
//private LiveData<List<PlaceModel>> allPlaces;
private LiveData<PlaceModel> place;
public PlaceViewModel(@NonNull Application application, @NonNull SavedStateHandle savedStateHandle) { // <-- activity 1.1.0+, lifecycle 2.2.0+
super(application);
repository = new PlaceRepository(application);
//allPlaces = repository.getAllPlaces();
place = Transformations.switchMap(savedStateHandle.<String>getLiveData(DetailActivity.EXTRA_PLACE_ID), (id) -> repository.getPlaceById(id));
}
//public LiveData<List<PlaceModel>> getAllPlaces() {
// return allPlaces;
//}
//public LiveData<PlaceModel> getPlaceById(String id) {
// return repository.getPlaceById(id);
//}
public LiveData<PlaceModel> getPlace() {
return place;
}
public void insert(PlaceModel place) {
repository.insert(place);
}
public void delete(PlaceModel place) {
repository.delete(place);
}
public void update(PlaceModel place) {
repository.update(place);
}
}
在我的 MainActivity 中,我在适配器中显示了项目。这些项目是房间实体对象。当我单击适配器中的一个项目时,我会启动一个 DetailActivity。
现在,在此 DetailActivity 中,我想使用 ViewModel 和 Entity 对象的 ID 获取点击的项目。
我的问题是,我不确定该怎么做。我应该使用 LiveData 吗?我很困惑,因为像 this Google Codelab 这样的例子总是在 LiveData 中包装 Entity 对象,所以要获取对象本身,你必须观察 onChanged
的变化并使用方法的参数。
我目前的做法是在 MainActivity 中使用 Intent putExtra
将项目的 ID 发送到 DetailActivity:
/** Called when an item in the places list is clicked.
*
* @param view The view displaying place name and address
* @param position The position of the place item
*/
@Override
public void onItemClick(View view, int position) {
// start DetailActivity
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra(EXTRA_PLACE_ID, adapter.getItem(position).getPlaceId());
// get the position that was clicked
// This will be used to save or delete the place from the DetailActivity buttons
clickedPlacePos = position;
startActivityForResult(intent, DETAIL_ACTIVITY_REQUEST_CODE);
}
然后在DetailActivity中,获取ID后,通过ID与ViewModel获取Entity对象:
viewModel = new ViewModelProvider(this).get(PlaceViewModel.class);
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_PLACE_ID)) {
String id = intent.getStringExtra(EXTRA_PLACE_ID);
viewModel.getPlaceById(id).observe(this, new Observer<PlaceModel>() {
@Override
public void onChanged(PlaceModel placeModel) {
// placeModel will be null if place is deleted
if (placeModel != null) {
place = placeModel;
// rest of code using this object is put here
}
}
});
}
这是通过 ID 获取单个项目的常用方法吗?或者有更简单的方法吗?
看起来有点复杂,而且所有使用该对象的代码都必须放在onChanged
中,否则该对象将为空。此外,该代码的上下文将不再是 DetailActivity。我是 Android.
完整代码为here。
PlaceDao 方法:
@Query("SELECT * FROM place_table WHERE place_id =:id")
LiveData<PlaceModel> getPlaceById(String id);
PlaceRepository 方法:
LiveData<PlaceModel> getPlaceById(String id) {
return placeDao.getPlaceById(id);
}
PlaceViewModel:
import com.michaelhsieh.placetracker.model.PlaceModel;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
public class PlaceViewModel extends AndroidViewModel {
private PlaceRepository repository;
private LiveData<List<PlaceModel>> allPlaces;
public PlaceViewModel(@NonNull Application application) {
super(application);
repository = new PlaceRepository(application);
allPlaces = repository.getAllPlaces();
}
public LiveData<List<PlaceModel>> getAllPlaces() {
return allPlaces;
}
public LiveData<PlaceModel> getPlaceById(String id) {
return repository.getPlaceById(id);
}
public void insert(PlaceModel place) {
repository.insert(place);
}
public void delete(PlaceModel place) {
repository.delete(place);
}
public void update(PlaceModel place) {
repository.update(place);
}
}
Is this the usual approach to get a single item by ID? Or is there a simpler way?
通常的方法是,真正想要的,以 Jetpack 方式做事的现代方式否。但毫不奇怪,Google 没有更新他们的大部分文档,他们也没有更新他们在这方面的大部分示例资源。
无论如何,执行此操作的预期方法是依赖于 SavedStateHandle,并且 Transformations.switchMap。
viewModel = new ViewModelProvider(this).get(PlaceViewModel.class);
// Intent intent = getIntent();
// if (intent.hasExtra(EXTRA_PLACE_ID)) {
// String id = intent.getStringExtra(EXTRA_PLACE_ID);
viewModel.getPlace().observe(this, new Observer<PlaceModel>() {
@Override
public void onChanged(PlaceModel placeModel) {
// placeModel will be null if place is deleted
if (placeModel != null) {
place = placeModel;
// rest of code using this object is put here
}
}
});
和
public class PlaceViewModel extends AndroidViewModel {
private PlaceRepository repository;
//private LiveData<List<PlaceModel>> allPlaces;
private LiveData<PlaceModel> place;
public PlaceViewModel(@NonNull Application application, @NonNull SavedStateHandle savedStateHandle) { // <-- activity 1.1.0+, lifecycle 2.2.0+
super(application);
repository = new PlaceRepository(application);
//allPlaces = repository.getAllPlaces();
place = Transformations.switchMap(savedStateHandle.<String>getLiveData(DetailActivity.EXTRA_PLACE_ID), (id) -> repository.getPlaceById(id));
}
//public LiveData<List<PlaceModel>> getAllPlaces() {
// return allPlaces;
//}
//public LiveData<PlaceModel> getPlaceById(String id) {
// return repository.getPlaceById(id);
//}
public LiveData<PlaceModel> getPlace() {
return place;
}
public void insert(PlaceModel place) {
repository.insert(place);
}
public void delete(PlaceModel place) {
repository.delete(place);
}
public void update(PlaceModel place) {
repository.update(place);
}
}