【问题标题】:Get item by ID using ViewModel使用 ViewModel 按 ID 获取项目
【发布时间】:2020-07-22 22:52:22
【问题描述】:

在我的 MainActivity 中,我在适配器中显示了项目。这些项目是房间实体对象。当我单击适配器中的一个项目时,我会启动一个 DetailActivity。

现在在这个 DetailActivity 中,我想使用 ViewModel 和 Entity 对象的 ID 来获取点击的项目。

我的问题是,我不知道该怎么做。我应该使用 LiveData 吗?我很困惑,因为像 this Google Codelab 这样的示例总是将实体对象包装在 LiveData 中,因此要获取对象本身,您必须使用 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后,用ViewModel通过ID获取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);
    }

}

【问题讨论】:

    标签: java android android-room android-viewmodel


    【解决方案1】:

    这是通过 ID 获取单个项目的常用方法吗?还是有更简单的方法?

    通常的方法是的,实际上是用 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);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-20
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多