我正在与Firestore合作,并使用ItemKeyedDataSource
成功地将其与分页库集成在一起。这是要点:
public class MessageDataSource extends ItemKeyedDataSource<Query, Message> {
//... private members
MessageDataSource(Query query) {
mQuery = query;
}
@Override
public void loadInitial(@NonNull LoadInitialParams<Query> params, @NonNull LoadInitialCallback<Message> callback) {
mLoadStateObserver.postValue(LoadingState.LOADING);
mQuery.limit(params.requestedLoadSize).get()
.addOnCompleteListener(new OnLoadCompleteListener() {
@Override
protected void onSuccess(QuerySnapshot snapshots) {
getLastDocument(snapshots);
// I'm able to get the values here
List<Message> m = snapshots.toObjects(Message.class);
for (Message message : m) {
Log.d(TAG, "onSuccess() returned: " + message.getTitle());
}
callback.onResult(snapshots.toObjects(Message.class));
}
@Override
protected void onError(Exception e) {
Log.w(TAG, "loadInitial onError: " + e);
}
});
}
@Override
public void loadAfter(@NonNull LoadParams<Query> params, @NonNull LoadCallback<Message> callback) {
Log.d(TAG, "LoadingState: loading");
mLoadStateObserver.postValue(LoadingState.LOADING);
params.key.limit(params.requestedLoadSize).get()
.addOnCompleteListener(new OnLoadCompleteListener() {
@Override
protected void onSuccess(QuerySnapshot snapshots) {
getLastDocument(snapshots);
callback.onResult(snapshots.toObjects(Message.class));
}
@Override
protected void onError(Exception e) {
Log.w(TAG, "loadAfter onError: " + e);
}
});
}
private void getLastDocument(QuerySnapshot queryDocumentSnapshots) {
int lastDocumentPosition = queryDocumentSnapshots.size() - 1;
if (lastDocumentPosition >= 0) {
mLastDocument = queryDocumentSnapshots.getDocuments().get(lastDocumentPosition);
}
}
@Override
public void loadBefore(@NonNull LoadParams<Query> params, @NonNull LoadCallback<Message> callback) {}
@NonNull
@Override
public Query getKey(@NonNull Message item) {
return mQuery.startAfter(mLastDocument);
}
/*
* Public Getters
*/
public LiveData<LoadingState> getLoadState() {
return mLoadStateObserver;
}
/* Factory Class */
public static class Factory extends DataSource.Factory<Query, Message> {
private final Query mQuery;
private MutableLiveData<MessageDataSource> mSourceLiveData = new MutableLiveData<>();
public Factory(Query query) {
mQuery = query;
}
@Override
public DataSource<Query, Message> create() {
MessageDataSource itemKeyedDataSource = new MessageDataSource(mQuery);
mSourceLiveData.postValue(itemKeyedDataSource);
return itemKeyedDataSource;
}
public LiveData<MessageDataSource> getSourceLiveData() {
return mSourceLiveData;
}
}
}
然后在MessageViewModel
类的构造函数中:
MessageViewModel() {
//... Init collections and query
// Init Paging
MessageDataSource.Factory mFactory = new MessageDataSource.Factory(query);
PagedList.Config config = new PagedList.Config.Builder()
.setPrefetchDistance(10)
.setPageSize(10)
.setEnablePlaceholders(false)
.build();
// Build Observables
mMessageObservable = new LivePagedListBuilder<>(mFactory, config)
.build();
mLoadStateObservable = Transformations.switchMap(mMessageObservable, pagedListInput -> {
// No result here
Log.d(TAG, "MessageViewModel: " + mMessageObservable.getValue());
MessageDataSource dataSource = (MessageDataSource) pagedListInput.getDataSource();
return dataSource.getLoadState();
});
}
注意这种情况:
当我在MainActivity#oncreate
方法中初始化视图模型并进行观察时,它正在按预期方式工作,并且能够在recyclerview中查看它。
稍后,我决定创建一个Fragment并通过将所有逻辑移到Fragment来对其进行重构,当我尝试观察相同的livedata时,不返回任何值。这是我的方法。
在片段内:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
mViewModel = ViewModelProviders.of(getActivity()).get(MessageViewModel.class);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//...
mViewModel.getMessageObserver().observe(this, messages -> {
Log.d(TAG, "onCreateView() returned: " + messages.size());
});
mViewModel.getLoadingStateObserver().observe(this, loadingState -> {
Log.d(TAG, "onCreateView() returned: " + loadingState.name());
});
return view;
}
有趣的部分:
loadstate
返回值LOADING
和SUCCESS
MessageDataSource
中,查询的值已成功返回,但是在Fragment中观察到该值时,我没有任何值。我在这里做什么错了?
P.S:我正在学习Android。
答案 0 :(得分:0)
使用碎片可能会发生一些问题。在onActivityCreated()中设置了观察者,以确保创建视图并将观察语句中的“ this”更改为“ getViewLifecycleOwner()”。例如,这可以防止观察者在将片段从后堆栈弹出后多次触发。您可以阅读有关here的信息。 因此,将您的观察者更改为:
Activity
答案 1 :(得分:0)
Share data between fragments上显示的示例代码几乎是最少的,只是看了一下,我才得到了错误的概述,直到我非常仔细地阅读了这一部分:
这些片段可以使用其活动范围共享ViewModel 处理此通信,如以下示例所示 代码:
因此,基本上,您必须在Activity
中初始化视图模型:ViewModelProviders.of(this).get(SomeViewModel.class);
然后在活动的片段上,可以将其初始化为:
mViewModel = ViewModelProviders.of(getActivity()).get(SomeViewModel.class);
mViewModel.someMethod().observe(this, ref -> {
// do things
});
这是我做错的,现在已解决。