使用实时数据库时使用不同的RecyclerView项目布局

时间:2017-07-19 18:04:26

标签: android firebase firebase-realtime-database

我希望在点击recyclerview中的项目后,使用不同的数据填充Recyclerview(并采用不同的布局)。用于填充recyclerview的数据来自firebase实时数据库。单击某个项目时,recyclelerview应显示所选节点的子节点。而不是开始一个新的活动和膨胀一个全新的布局。我想尝试更改单个布局的一部分。我认为在渲染,内存和电池性能方面可能会有性能优势(并且还有较小的apk,因为要包含的文件较少)。我知道我需要分析代码并将其与我有多个活动的情况进行比较,但首先我想让代码在数据库中上下移动。我的MainFragment包含一个侦听器,它在适配器类中为recyclerview调用(如下所示)。

@Override
public void setItemLayoutResuorce(String key) {
    Log.i("Hilarity", "SILR");
    mMessagesDatabaseReference = mMessagesDatabaseReference.child(key);
    Log.i("Hilarity", mMessagesDatabaseReference.getKey());
    mChildEventListener = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            if (mMessagesDatabaseReference.getKey().equals(getString(R.string.languages))) {
                String langauge = dataSnapshot.getKey();
                languages.add(langauge);
                jokeAdapter.notifyItemInserted(languages.size() - 1);
                jokeAdapter.notifyDataSetChanged();
                Log.i("Hilarity", "languages add");
            } else {
                Log.i("Hilarity", "joke added");
                Joke joke = dataSnapshot.getValue(Joke.class);
                jokes.add(joke);
                jokeAdapter.notifyItemInserted(jokes.size() - 1);
                jokeAdapter.notifyDataSetChanged();
            }
        }

        public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
        public void onChildRemoved(DataSnapshot dataSnapshot) {}
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
        public void onCancelled(DatabaseError databaseError) {}
    };
    mMessagesDatabaseReference.addChildEventListener(mChildEventListener);
    jokeAdapter = new JokeAdapter(getActivity(), jokes, languages, this, true);
    recyclerview.setAdapter(jokeAdapter);

在Adapter.ViewHolder.onClick()中调用它(如下所示)

@Override
    public void onClick(View view){
        if (view instanceof TextView) {
            showJokes = true;
            TextView textView = (TextView) view;
            rvc.setItemLayoutResuorce(textView.getText().toString());
        }
    }

当我点击一个回收者视图项并且需要使用数据重新填充recyclerview时会出现致命错误,但是还没有数据(还有),我在Adapter.onBindViewHolder中得到了一个索引超出范围的异常。它就像childEventListener一样,即使它在我创建的监听器中重新获得(它最初是在MainFragment.onCreate()中创建的),也不会被重置。

如何在单击按钮后让数据库发送新数据(其他一切似乎都有效,我需要使用新的布局资源来填充recyclerview的数据)?你认为用C ++编写这部分代码并手动删除(然后创建)对DatabaseReference和ChildEventListener对象的引用会起作用吗?

1 个答案:

答案 0 :(得分:0)

您似乎在后台线程中直接从数据源(在您的情况下为Firebase)更新RecyclerView内容。

最佳做法是收集您在后台线程中的RecyclerView中显示的所有数据,将其保存到UI线程上的本地副本(本地ArrayList或Map,取决于您的数据结构),并且仅在请求内容更新后来自notifyDataSetChanged()的适配器或不同的更新方法。

同样在你的代码中我发现了冗余调用:

jokeAdapter.notifyItemInserted(jokes.size() - 1);
jokeAdapter.notifyDataSetChanged();

调用notifyDataSetChanged()后无需立即调用notifyItemInserted(),因为第一次更新应将适配器中的所有项目从指定位置更新到最后一位。对notifyDataSetChanged的额外调用只会重复更新,但适用于所有项目。