【问题标题】:RecyclerView Adapter is loading every time firebase database data gets updated每次更新 Firebase 数据库数据时,RecyclerView 适配器都会加载
【发布时间】:2017-08-04 21:29:33
【问题描述】:

我是 Firebase 的新手。我正在尝试更新我在 firebase 数据库中的 RecyclerView 数据,同时在我的 RecyclerView 数据中动态反映相同的更新值。即使有人尝试从 firebase 控制台本身更新数据,更改也必须反映在 recyclerView 中。 我的列表中有一个 seekBar,每次我更改列表中的数据时,它都必须反映在数据库中。问题是,每次我尝试从 recyclerView 列表本身更改数据时,firebase 数据库中的数据都会发生变化,这反过来又调用 onDataChanged() 并让我的整个 recyclerView 再次重新加载而不显示更新的数据名单。请帮忙。

    Below  I am posting my listfragment as well as adapter class code:

    ListFragment:

         @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment

            View v= inflater.inflate(R.layout.fragment_slc_list, container, false);
            slcList = (RecyclerView)v.findViewById(R.id.addedSlcList);
            noSLC = (TextView)v.findViewById(R.id.noSLCText);
            fragmentManager= myContext.getSupportFragmentManager();
            slcList.setHasFixedSize(true);
            ref = new Firebase(Config.FIREBASE_URL);
            list = new ArrayList<slcItem>();
            LinearLayoutManager llm = new LinearLayoutManager(getActivity());
    //        dAdapter = new slcListAdapter(myContext,list, ref );
    //        slcList.setLayoutManager(llm);
    //        slcList.setAdapter(dAdapter);
            ref.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot)
                {
                    Log.d("clear","cleared");
                    list.clear();
                    for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
                        Log.v("2nd",""+ childDataSnapshot.getKey()); //displays the key for the node
                        Log.v("2nd",""+ childDataSnapshot.getValue());
                        Slc val= childDataSnapshot.getValue(Slc.class);
                        Log.v("2ndClass",""+ val.getOn_off());
                        slcItem item = new slcItem();
                        item.setSlcOnOff(val.getOn_off());
                        item.setSlcID(val.getUser_id());
                        item.setSlcProgress(val.getDimming_val());
                        item.setSlcName(childDataSnapshot.getKey());
                        item.setSlcStatus(val.getStatus());
                        list.add(item);
                        LinearLayoutManager llm1 = new LinearLayoutManager(getActivity());
                        dAdapter = new slcListAdapter(myContext,list, ref );
                        dAdapter.notifyDataSetChanged();
                        slcList.setLayoutManager(llm1);
                        slcList.setAdapter(dAdapter);
                    }
                    for(int i=0; i<list.size();i++)
                    {
                        Log.d("animesh",list.get(i).getSlcName()+" "+list.size()+" "+dataSnapshot.getChildrenCount());
                    }
                    if(dataSnapshot.getChildrenCount() == 0)
                    {
                        LinearLayoutManager llm1 = new LinearLayoutManager(getActivity());
                        dAdapter = new slcListAdapter(myContext,list, ref );
                        getActivity().runOnUiThread(new Runnable() {
                            public void run() {
                                dAdapter.notifyDataSetChanged();
                            }
                        });
                        slcList.setLayoutManager(llm1);
                        slcList.setAdapter(dAdapter);
                    }
                }

                @Override
                public void onCancelled(FirebaseError firebaseError)
                {
                    Log.d("animesh",firebaseError+"");
                }
            });
            Log.d("anilist",list.size()+"");

Adapter class:

    public slcListAdapter(Context context,ArrayList<slcItem> list, Firebase ref ) {
        super();
        this.context=context;
        this.list=list;
        this.ref=ref;

        dItems = new ArrayList<slcItem>();
        for(int i=0;i<list.size();i++)
        {
            slcItem deal = new slcItem();
        deal.setSlcName(list.get(i).getSlcName());
        dItems.add(deal);
        }



        }

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext())
        .inflate(R.layout.single_slc_row, viewGroup, false);
        viewHolder = new ViewHolder(v);
        return viewHolder;
        }

@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
        int v;

         nature = dItems.get(i);
         ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot)
            {
                for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren())
                {
                    Log.d("animesh",childDataSnapshot.toString());
                    Slc val = childDataSnapshot.getValue(Slc.class);
//                    viewHolder.dimming.setProgress(val.getDimming_val());
                }

            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        });

        viewHolder.name.setText(nature.getSlcName());
        viewHolder.inv.setVisibility(View.GONE);

        viewHolder.onOff.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                                         boolean isChecked) {
                Log.d("checkani",nature.getSlcName());
                if(isChecked){
                    ref.child(list.get(i).getSlcName()).child("on_off").setValue(1);


                }else{
                    ref.child(list.get(i).getSlcName()).child("on_off").setValue(0);
                    Log.d("Ani",list.get(i).getSlcName());
                }

            }
        });
    viewHolder.dimming.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
    {

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
        {
           Log.d("dimming",nature.getSlcName());

            ref.child(list.get(i).getSlcName()).child("dimming_val").setValue(progress);

        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
        viewHolder.expand.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)
            {
               // ViewAnimationsUtils.expand(viewHolder.inv);
                viewHolder.collapse.setVisibility(View.VISIBLE);
                viewHolder.inv.setVisibility(View.VISIBLE);
                viewHolder.expand.setVisibility(View.GONE);
            }
        });
        viewHolder.collapse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)
            {
               // ViewAnimationsUtils.collapse(inv);
                viewHolder.inv.setVisibility(View.GONE);
                viewHolder.expand.setVisibility(View.VISIBLE);
                viewHolder.collapse.setVisibility(View.GONE);
            }
        });
    viewHolder.edit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v)
        {
            final Dialog dialog = new Dialog(context);
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.update_slc);
            dialog.setCancelable(false);
            Window window = dialog.getWindow();
            if(window == null) return;
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
            lp.copyFrom(dialog.getWindow().getAttributes());
            lp.width = WindowManager.LayoutParams.MATCH_PARENT;
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
            lp.gravity = Gravity.CENTER;
            dialog.getWindow().setAttributes(lp);
            final EditText name = (EditText) dialog.findViewById(R.id.slcNameu);
            final EditText id = (EditText) dialog.findViewById(R.id.slcIDu);
            TextView cancel = (TextView) dialog.findViewById(R.id.cancelu);
            TextView update = (TextView) dialog.findViewById(R.id.updateSlc);
//            update.setOnClickListener(new View.OnClickListener() {
//                @Override
//                public void onClick(View v)
//                {
//                    final String Sname = nature.getSlcName();
//                    Map mParent = new HashMap();
//                    mParent.put("user_id", id.getText().toString().trim());
//                    mParent.put("on_off", nature.getSlcOnOff());
//                    mParent.put("status", nature.getSlcStatus());
//                    mParent.put("dimming_val",nature.getSlcProgress());
//                    ref.child(name.getText().toString().trim()).setValue(mParent, new Firebase.CompletionListener()
//                    {
//                        @Override
//                        public void onComplete(FirebaseError firebaseError, Firebase firebase) {
//                            Log.d("aniNature","Value was set. Error = "+firebaseError+" "+nature.getSlcName()+" "+Sname);
//                            ref.child(Sname).removeValue();
//                            dialog.dismiss();
//                        }
//                    });
//
//                }
//            });
            cancel.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });


            dialog.show();

        }
    });
    viewHolder.delete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final Dialog dialog = new Dialog(context);
            dialog.setTitle("Delete Slc?");
            dialog.setContentView(R.layout.delete_slc);
            dialog.setCancelable(false);
            Window window = dialog.getWindow();
            if(window == null) return;
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
            lp.copyFrom(dialog.getWindow().getAttributes());
            lp.width = WindowManager.LayoutParams.MATCH_PARENT;
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
            lp.gravity = Gravity.CENTER;
            dialog.getWindow().setAttributes(lp);
            TextView delete = (TextView)dialog.findViewById(R.id.deleteSlc);
            delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v)
                {
                    Log.d("delete1",nature.getSlcName());
                    ref.child(list.get(i).getSlcName()).removeValue();
                    Log.d("delete",nature.getSlcName());
                    dialog.dismiss();
                }
            });


            TextView dialogButton = (TextView) dialog.findViewById(R.id.canceld);
            // if button is clicked, close the custom dialog
            dialogButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v)
                {
                    dialog.dismiss();
                }
            });

            dialog.show();
        }
    });

        }

@Override
public int getItemCount()
{

        return dItems.size();
}

class ViewHolder extends RecyclerView.ViewHolder{

    public TextView name;
    public Switch onOff;
    public SeekBar dimming;
    public TextView edit;
    public TextView delete;
    public TextView expand;
    public TextView collapse;
    public LinearLayout inv;

    public ViewHolder(View itemView)
    {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.slcName);
        onOff = (Switch) itemView.findViewById(R.id.slcONOFFSwich);
        dimming=(SeekBar) itemView.findViewById(R.id.slcDimming);
        edit = (TextView) itemView.findViewById(R.id.EditSlc);
        delete = (TextView) itemView.findViewById(R.id.DeleteSlc);
        expand = (TextView) itemView.findViewById(R.id.down);
        collapse = (TextView) itemView.findViewById(R.id.up);
        inv = (LinearLayout) itemView.findViewById(R.id.invisibleLayout);
    }
}

}

【问题讨论】:

  • 请查看 Firebase 的 addListenerForSingleValueEvent
  • @LalitJadav 谢谢谢谢....:),但它不适用于控制台页面上的删除或更新等更改。
  • 它只读取一次数据

标签: android firebase firebase-realtime-database android-recyclerview


【解决方案1】:

如果您想响应子级更改,您应该使用ChildEventListener。当添加、删除、更改或移动子项时,此接口具有单独的方法(分别为onChildAddedonChildRemovedonChildChangedonChildMoved)。

请注意,在这种情况下,您需要做更多的工作以确保项目在list 中保持正确的顺序。例如:您需要跟踪每个项目的键,以便您可以将其与onChildAddedonChildChanged 中的previousKey 参数进行比较。

对于此类适配器的工作实现示例,我建议查看 FirebaseUI 的 FirebaseRecyclerAdapter 及其底层 FirebaseArray

【讨论】:

  • 谢谢,recyclerView 现在是动态的,但是当我试图从 recyclerView 中删除一个项目时,我收到 IndexOutOfBoundsException @Frank
【解决方案2】:

不要使用addValueEventListener,而是使用addListenerForSingleValueEvent,这只会从 Firebase 获取您的数据一次,并且不会监听更新。

查看this website for detailed documentation

一次读取数据

在某些情况下,调用一次回调然后立即删除可能很有用。我们创建了一个辅助函数来简化此操作:

ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    // ...
}

@Override
public void onCancelled(DatabaseError databaseError) {
    // ...
}
});

【讨论】:

  • 它工作正常,但同样不能用于控制台页面上的删除或更新等更改。@Ruben Aalders
  • 好的,我可能没有完全理解你的问题。你能详细说明一下吗?
  • 当你在recyclerView中改变某些东西时,它会反映在数据库中。同样,如果您要更改数据库中的某些内容,则必须反映在 RecyclerView 项目中,就像更新或删除项目一样。
【解决方案3】:

你需要在监听器中改变这个:

LinearLayoutManager llm1 = new LinearLayoutManager(getActivity());
                        dAdapter = new slcListAdapter(myContext,list, ref );
                        dAdapter.notifyDataSetChanged();
                        slcList.setLayoutManager(llm1);
                        slcList.setAdapter(dAdapter);

这将在每次数据更改时设置新的适配器。您必须维护列表并跟踪该列表。每次发生项目更改时,只需在您的列表中编辑它并仅通知这些更改。

无需每次都创建新的适配器

【讨论】:

    猜你喜欢
    • 2021-10-14
    • 1970-01-01
    • 2019-12-07
    • 2016-09-14
    • 2019-02-20
    • 2011-02-04
    • 1970-01-01
    • 2015-09-30
    相关资源
    最近更新 更多