【发布时间】:2021-03-28 15:22:12
【问题描述】:
我有一个片段,其中显示了专辑的图像和可能的子专辑。该片段有一个参数,即要显示的专辑的 ID。 ID 是 POD long。用于导航,包括。正确的导航历史记录并将参数传递给片段,我使用导航图和 SafeArgs 库。
单击子专辑会导航到具有要显示的子专辑 ID 的同一片段。图像和子相册的加载是在视图模型中完成的。
问题:如何将专辑的 ID 作为构造函数的参数传递给我的视图模型。
这里有一些代码 sn-ps 可能有助于理解问题
片段
public class AlbumFragment extends Fragment implements Observer<List<AlbumEntry>> {
private AlbumViewModel viewModel;
private long albumID; /*< The ID of the album which is shown by this instance of the fragment */
public static AlbumFragment newInstance( final long albumID ) {
AlbumFragment fragment = new AlbumFragment();
// The class `AlbumFragmentArgs` is auto-generated by the SafeArgs library
fragment.setArguments(
(new AlbumFragmentArgs.Builder()).setAlbumID( albumID ).build().toBundle()
);
return fragment;
}
@Override
public void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
albumID = AlbumFragmentArgs.fromBundle( getArguments() ).getAlbumID();
// TODO: We somehow need to pass the ID of the album to the view model
viewModel = new ViewModelProvider( this ).get( AlbumViewModel.class );
}
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState ) {
// Inflates the view from XML layout file, skipped here
return view;
}
@Override
public void onViewCreated( @NonNull final View view, final Bundle savedInstanceState ) {
// PROBLEM: The list of album entries actually depends on the current album
// The ID of the current album should have been passed when then model was created
LiveData<? extends List<AlbumEntry>> liveAlbumEntries = viewModel.getAlbumEntries();
liveAlbumEntries.observe( this.getViewLifecycleOwner(), this );
}
// Methods for observing live data skipped here
protected void onClick( final View view ) {
// The code how the ID of the target album is obtained from the
// clicked view is left out here
// The variable is targetAlbumID
NavGraphDirections.ActionToAlbumFragment action = NavGraphDirections.actionToAlbumFragment();
action.setAlbumID( targetAlbumID );
Navigation.findNavController( this.getView() ).navigate( action );
}
}
视图模型
public class AlbumViewModel extends AndroidViewModel {
private long albumID; /*< The ID of the album which is shown by this instance of the fragment */
public AlbumViewModel( Application application /*, final long albumID */ ) {
super( application );
// TODO: How to write a constructor which gets an Application object and an albumID?
/* this.albumID = albumID */
// Remaining code, esp. initialization of the repository, is left out
}
public LiveData<? extends List<AlbumEntry>> getAlbumEntries() {
// Code left out, but depends on `this.albumID`
}
}
一些最后的评论
当然,也可以不将当前专辑的 ID 传递给视图模型,但始终将专辑 ID 作为附加参数显式传递给视图模型的每个方法,例如 LiveData<? extends List<AlbumEntry>> liveAlbumEntries = viewModel.getAlbumEntries( albumID )。
但是,为每个专辑 ID 拥有一个视图模型实例会容易得多,尤其是在缓存方面。如果视图模型的单个实例绑定到特定的专辑 ID,则视图模型只需要处理该专辑的专辑条目。如果同一专辑 ID 的相应片段永久结束其生命周期,则相应的视图模型将被销毁,因此专辑条目将从内存中删除。如果仅重新创建片段(由于配置更改),则相应的视图模型将保存在内存中,专辑条目也是如此。
相反,如果我对所有专辑和片段的所有实例只有一个应用程序范围的全局实例 AlbumViewModel,并且如果专辑 ID 显式传递给 AlbumViewModel 的每个方法,我永远不会知道,当特定片段被销毁,并且专辑条目可以从内存中删除。
【问题讨论】:
-
我链接的问题的标题可能不同,但与您遇到的问题相同。解决方案是为您的视图模型创建一个自定义视图模型工厂,并将专辑 ID 传递给构造函数。 medium.com/koderlabs/…
标签: android-architecture-components android-viewmodel