【发布时间】:2017-09-18 02:09:39
【问题描述】:
我正在开发一个显示项目列表并允许用户添加更多项目并检查项目详细信息的应用程序。
假设我在活动中保留我的数据库引用,添加ChildEventListener 侦听器onResume() 并在onPause() 上删除它们:
public void onResume() {
super.onResume();
mItemChildEventListener = mDatabaseReference.child('items').addChildEventListener(new ChildEventListener() {
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
mAdapter.addItem(dataSnapshot.getValue(Item.class));
}
...
};
}
public void onPause() {
super.onPause();
if (mItemChildEventListener != null) {
mDatabaseReference.removeEventListener(mItemChildEventListener);
}
}
在这些ChildEventListener 中,我将逐项添加到项目列表中,并在适配器中调用notifyItemInserted(itemArray.size() - 1)。
public void addItem(Item item) {
if (mItems == null) {
mItems = new ArrayList<>();
}
mItems.add(item);
notifyItemInserted(mItems.size() - 1);
}
另外,为了让应用程序顺利运行,我将项目列表保存在 Reteiner Fragment 中,将这些值保存在 onSaveInstanceState() 并在 onCreate() 上恢复它们。
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
mItems = getState(STATE_ITEMS);
} else {
mItems = new ArrayList<>();
}
mAdapter = new ItemAdapter(mItems);
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState(STATE_ITEMS, mItems);
}
public <T> T getState(String key) {
//noinspection unchecked
return (T) mRetainedFragment.map.get(key);
}
public void saveState(String key, Object value) {
mRetainedFragment.map.put(key, value);
}
public static class RetainedFragment extends Fragment {
HashMap<String, Object> map = new HashMap<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
}
但是,如果我取消注册并再次注册侦听器,例如,通过任何方向更改或离开和返回活动,如预期的那样,将调用 onResume(),并再次添加 ChildEventListener,同样数据被检索,如果它没有与项目列表中已经包含的数据进行比较,mItems,它将被复制。
另外,如果我不保留项目列表mItems,并在每次调用onResume() 时检索数据,列表将失去滚动位置并且还会闪烁,因为检索数据需要一些时间.
问题
如何保持检索到的项目列表而不再次检索它们,但继续监听已检索项目的变化和添加的新项目?是否有比将已检索到的项目与新项目进行比较(例如,通过它们的键)更好的解决方案?
我已尝试查看文档和其他问题,但找不到与这种情况相关的任何信息。另外,我试图在onSaveInstanceState() 中保留对mDatabaseReference 的引用,就像我对mItems 的项目列表所做的那样,但它也没有工作。
【问题讨论】:
-
@rewgoes 您是否有一个 DatabaseHelper 类,并且您是否使用 RecyclerAdapter 作为 View Holder,如果您可以将数据加载到 ArrayList 中,那么您只需在添加时访问数据库更新或删除,这是我与 Sqlite 一起使用的 MVP 设计
-
@grendel,我没有使用 DatabaseHelper。我的数据库完全基于 firebase 实时数据库。
-
@MarianoCórdoba 仅凭这些模式不一定能解决 OP 遇到的问题。您以这种方式构建的基础架构仍然容易因每次配置更改而被拆除和重新创建,除非您仍然做一些特殊的事情来保留您的数据模型层。
标签: android firebase firebase-realtime-database