使用 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);
    }

}