当只添加一个项目时,Recyclerview添加多个项目

时间:2019-07-23 02:37:04

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

首先,我研究了现有的问题,这些问题与我的问题类似。主要是这个答案是我遇到的问题的壁橱-> Link。我没有找到适合我问题的解决方案。

我已经在HomeFragment和HomeListAdapter的代码下方附加了代码。我已经做过一些研究,有人说我不应该在bindviewholder中进行firebase数据库调用,但是我正在遵循Firebase快速入门数据库示例,因此,如果有任何firebase android工程师可能会给我一些指导,那将是很棒的。

当我单击“编辑配方片段”上的“添加”时。上载完成后,它将转到主片段。我的困惑是我在应用程序中拥有的所有其他适配器都具有正确的行为。它只会添加一个配方(一次只能添加一个是预期的行为)。

HomeFragment

package com.irondigitalmedia.keep;


import java.util.ArrayList;


public class HomeFragment extends BaseFragment {

    private static final String TAG = HomeFragment.class.getSimpleName();

    private ArrayList<Recipe> mRecipeList;
    private ArrayList<String> mRecipeIds;
    private RecyclerView HomeRecyclerView;
    private HomeListAdapter adapter;
    private LinearLayoutManager LLM;
    private Context mContext;
    private FirebaseDatabase database;
    private DatabaseReference myRef;
    private Recipe mRecipe;
    private User mUser;
    private int likeCounter = 0;
    private MainActivity mainActivity;
    private BaseActivity baseActivity;
    private Toolbar toolbar;
    private ProgressBar progressBar;

    public HomeFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_home,container,false);

        mContext = view.getContext();
        mRecipeList = new ArrayList<>();
        mRecipeIds = new ArrayList<>();

        HomeRecyclerView = view.findViewById(R.id.frag_search_rv);
        HomeRecyclerView.addItemDecoration(new SpacesItemDecoration(8));
        LLM = new LinearLayoutManager(getContext());
        HomeRecyclerView.setLayoutManager(LLM);
        adapter = new HomeListAdapter(mContext, mRecipeList, mUser);
        HomeRecyclerView.setAdapter(adapter);

        mainActivity = (MainActivity) view.getContext();
        mainActivity.mMainNav.setSelectedItemId(R.id.nav_home);
        toolbar = mainActivity.findViewById(R.id.main_toolbar);
        toolbar.setTitle("Home");
        mainActivity.setSupportActionBar(toolbar);

        if(savedInstanceState != null){
            Log.e(TAG, "onCreateView: savedInstanceState is null");
        }else{
            LoadRecipes();
        }

        return view;
    }

    private void LoadRecipes() {
        database = FirebaseDatabase.getInstance();
        myRef = database.getReference();

        myRef.child(Constants.DATABASE_ROOT_FOLLOWING).child(getUid()).addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                String key = dataSnapshot.getKey();
                Log.i(TAG, "onChildAdded: key is = " + key);
                if(key!=null){
                    Log.i(TAG, "onChildAdded: key is not null ");
                    myRef.child(Constants.DATABASE_ROOT_USERS_RECIPES).child(key).limitToFirst(5).addChildEventListener(new ChildEventListener() {
                        @Override
                        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
                            Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());

                            // A new comment has been added, add it to the displayed list
                            mRecipe = dataSnapshot.getValue(Recipe.class);

                            // [START_EXCLUDE]
                            // Update RecyclerView
                            mRecipeIds.add(dataSnapshot.getKey());
                            mRecipeList.add(mRecipe);
                            adapter.notifyItemInserted(mRecipeList.size() - 1);
                            // [END_EXCLUDE]
                        }

                        @Override
                        public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
                            Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());

                            // A comment has changed, use the key to determine if we are displaying this
                            // comment and if so displayed the changed comment.
                            mRecipe = dataSnapshot.getValue(Recipe.class);
                            String recipeKey = dataSnapshot.getKey();

                            // [START_EXCLUDE]
                            int commentIndex = mRecipeIds.indexOf(recipeKey);
                            if (commentIndex > -1) {
                                // Replace with the new data
                                mRecipeList.set(commentIndex, mRecipe);

                                // Update the RecyclerView
                                adapter.notifyItemChanged(commentIndex);
                            } else {
                                Log.w(TAG, "onChildChanged:unknown_child:" + recipeKey);
                            }
                            // [END_EXCLUDE]
                        }

                        @Override
                        public void onChildRemoved(DataSnapshot dataSnapshot) {
                            Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());

                            // A comment has changed, use the key to determine if we are displaying this
                            // comment and if so remove it.
                            String recipeKey = dataSnapshot.getKey();

                            // [START_EXCLUDE]
                            int commentIndex = mRecipeIds.indexOf(recipeKey);
                            if (commentIndex > -1) {
                                // Remove data from the list
                                mRecipeIds.remove(commentIndex);
                                mRecipeList.remove(commentIndex);

                                // Update the RecyclerView
                                adapter.notifyItemRemoved(commentIndex);
                            } else {
                                Log.w(TAG, "onChildRemoved:unknown_child:" + recipeKey);
                            }
                            // [END_EXCLUDE]
                        }

                        @Override
                        public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
                            Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());

                            // A comment has changed position, use the key to determine if we are
                            // displaying this comment and if so move it.
                            mRecipe = dataSnapshot.getValue(Recipe.class);
                            String recipeKey = dataSnapshot.getKey();

                            // ...
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            Log.w(TAG, "recipes:onCancelled", databaseError.toException());
                            Toast.makeText(mContext, "Failed to load recipes.",
                                    Toast.LENGTH_SHORT).show();
                        }
                    });

                }else{
                    Log.e(TAG, "onChildAdded: Key is null");
                }


            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelableArrayList(Constants.SAVED_STATE_HOME,mRecipeList);
    }

    @Override
    public void onStart() {
        super.onStart();
        getActivity().setTitle("Home");
    }

    public String getUid() {
        return FirebaseAuth.getInstance().getCurrentUser().getUid();
    }



}

HomeListAdapter

package com.irondigitalmedia.keep.Adapters;

public class HomeListAdapter extends RecyclerView.Adapter<HomeListAdapter.ViewHolder> {
    private static final String TAG = HomeListAdapter.class.getSimpleName();
    private DatabaseReference mDatabase;
    private Context context;
    private List<Recipe> mRecipesList;
    private MainActivity mainActivity;
    private User user;
    private int likeCounter = 0;

    public HomeListAdapter(Context context, List<Recipe> mRecipesList, User user) {
        this.context = context;
        this.mRecipesList = mRecipesList;
        this.user = user;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_recipes_recipe_item, parent, false);

        mDatabase = FirebaseDatabase.getInstance().getReference();
        mainActivity = (MainActivity) view.getContext();

        return new HomeListAdapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        final Recipe recipe = mRecipesList.get(position);
        SetUserData(holder, position);
        holder.tv_recipe_title.setText(mRecipesList.get(position).getTitle());
        holder.tv_recipe_prepTime.setText(mRecipesList.get(position).getPrepTime());


        Glide.with(context).load(mRecipesList.get(position).getUrl())
                .placeholder(R.drawable.ic_loading).thumbnail(0.05f).fitCenter()
                .transition(DrawableTransitionOptions.withCrossFade()).centerCrop()
                .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
                .into(holder.recipe_thumbnail);

        Log.i(TAG, "onBindViewHolder: Database Reference = " +
                mDatabase.child(Constants.DATABASE_ROOT_RECIPES).child(recipe.getUid()).child(Constants.DATABASE_ROOT_LIKES));

        mDatabase.child(Constants.DATABASE_ROOT_RECIPES).child(recipe.getUid())
                .child(Constants.DATABASE_ROOT_LIKES).addValueEventListener(new ValueEventListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                likeCounter = (int) dataSnapshot.getChildrenCount();
                Log.i(TAG, "onDataChange: ChildrenCount = " + recipe.getTitle() + " " + likeCounter);
                holder.tv_like_counter.setText(Integer.toString(likeCounter));
            }


            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });



        mDatabase.child(Constants.DATABASE_ROOT_RECIPES).child(recipe.getUid())
                .child(Constants.DATABASE_ROOT_LIKES).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if(dataSnapshot.hasChild(getUid())){
                    holder.like.setLiked(true);
                    Log.i(TAG, "onDataChange: LIKED RECIPE...");
                }else{
                    Log.i(TAG, "onDataChange: RECIPE IS NOT LIKED...");
                    holder.like.setLiked(false);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


        mDatabase.child(Constants.DATABASE_ROOT_RECIPES).child(recipe.getUid())
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        if(dataSnapshot.hasChild(Constants.DATABASE_RECIPE_LIKE_COUNT_VALUE)){
                            holder.tv_like_counter.setText(String.valueOf(dataSnapshot.child(Constants.DATABASE_RECIPE_LIKE_COUNT_VALUE).getValue()));
                        }else{
                            // likes do not exist
                        }
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {

                    }
                });


        holder.like.setOnLikeListener(new OnLikeListener() {
            @Override
            public void liked(LikeButton likeButton) {
                Log.i(TAG, "liked: LIKED");
                // Add like
                holder.like.setLiked(true);
                mDatabase.child(Constants.DATABASE_ROOT_RECIPES).child(recipe.getUid()).child(Constants.DATABASE_ROOT_LIKES).child(getUid()).setValue("true");

            }

            @Override
            public void unLiked(LikeButton likeButton) {
                Log.i(TAG, "unLiked: UNLIKED");
                // remove Like
                holder.like.setLiked(false);
                mDatabase.child(Constants.DATABASE_ROOT_RECIPES).child(recipe.getUid()).child(Constants.DATABASE_ROOT_LIKES).child(getUid()).removeValue();

            }

        });



    }

    private void SetUserData(ViewHolder holder, int position) {
        mDatabase.child(Constants.DATABASE_ROOT_USERS).child(mRecipesList.get(position).getCreatorId())
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        User user = dataSnapshot.getValue(User.class);
                        holder.tv_user_username.setText(user.getUsername());
                        Glide.with(context).load(user.getUrl()).centerCrop().placeholder(R.drawable.ic_loading).into(holder.userPhoto);
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) {

                    }
                });
    }


    @Override
    public int getItemCount() {
        return mRecipesList.size();
    }


    public class ViewHolder extends RecyclerView.ViewHolder {

        public TextView tv_recipe_title, tv_recipe_prepTime, tv_user_username, tv_like_counter;
        public ImageView recipe_thumbnail;
        public LikeButton like;
        public CircleImageView userPhoto;
        public LinearLayout user_ll;
        public FirebaseAuth mAuth;
        public FirebaseDatabase mDatabase;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            mainActivity = (MainActivity) itemView.getContext();
            mDatabase = FirebaseDatabase.getInstance();
            tv_recipe_title = itemView.findViewById(R.id.recipe_item_title);
            tv_recipe_prepTime = itemView.findViewById(R.id.recipe_item_time);
            recipe_thumbnail = itemView.findViewById(R.id.recipe_item_photo);
            like = itemView.findViewById(R.id.recipe_item_image_like);
            tv_like_counter = itemView.findViewById(R.id.recipe_item_like_counter);
            userPhoto = itemView.findViewById(R.id.recipe_item_user_photo);
            tv_user_username = itemView.findViewById(R.id.recipe_item_user_username);
            user_ll = itemView.findViewById(R.id.recipe_item_user_linearLayout);

            user_ll.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ProfileFragment pf = new ProfileFragment();
                    if(pf.isAdded()){
                        return;
                    }else{
                        Bundle bundle = new Bundle();
                        bundle.putString(Constants.EXTRA_USER_UID,mRecipesList.get(getAdapterPosition()).getCreatorId());
                        Log.i(TAG, "onClick: Fragment Interaction recipe Creator Id = " + mRecipesList.get(getAdapterPosition()).getCreatorId());
                        FragmentTransaction ft = mainActivity.getSupportFragmentManager().beginTransaction();
                        pf.setArguments(bundle);
                        ft.replace(R.id.main_frame, pf, Constants.FRAGMENT_TAG_PROFILE);
                        ft.addToBackStack(Constants.FRAGMENT_TAG_PROFILE);
                        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                        ft.commit();
                    }
                }
            });

            itemView.setOnClickListener(v -> {
                RecipeDetailsFragment rd = new RecipeDetailsFragment();
                if(rd.isAdded()){
                    return;
                }else{
                    Bundle bundle = new Bundle();
                    bundle.putString(Constants.EXTRA_RECIPE_KEY,mRecipesList.get(getAdapterPosition()).getUid());
                    bundle.putString(Constants.EXTRA_RECIPE_CREATOR_ID, mRecipesList.get(getAdapterPosition()).getCreatorId());
                    Log.i(TAG, "onClick: Fragment Interaction recipe Key is = " + mRecipesList.get(getAdapterPosition()).getUid());
                    FragmentTransaction ft = mainActivity.getSupportFragmentManager().beginTransaction();
                    rd.setArguments(bundle);
                    ft.replace(R.id.main_frame, rd, Constants.FRAGMENT_TAG_RECIPE_DETAILS);
                    ft.addToBackStack(null);
                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                    ft.commit();
                }
            });
        }

    }

    public String getUid() {
        return FirebaseAuth.getInstance().getCurrentUser().getUid();
    }
}

EditRecipeFragment

package com.irondigitalmedia.keep.Adapters;



public class EditIngredientAdapter extends RecyclerView.Adapter<EditIngredientAdapter.IngredientViewHolder> {

    private static final String TAG = EditIngredientAdapter.class.getSimpleName();

    private String dataSnapShotKey;
    private Context mContext;
    private DatabaseReference mDatabaseReference;
    private ChildEventListener mChildEventListener;

    public List<String> mIngredientIds = new ArrayList<>();
    public List<Ingredient> mIngredients = new ArrayList<>();

    public EditIngredientAdapter(final Context mContext, DatabaseReference ref) {
        this.mContext = mContext;
        this.mDatabaseReference = ref;


        // Create child event listener
        // [START child_event_listener_recycler]
        ChildEventListener childEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
                dataSnapShotKey = dataSnapshot.getKey();
                // A new comment has been added, add it to the displayed list
                Ingredient ingredient = dataSnapshot.getValue(Ingredient.class);

                // [START_EXCLUDE]
                // Update RecyclerView
                mIngredientIds.add(dataSnapshot.getKey());
                mIngredients.add(ingredient);
                notifyItemInserted(mIngredients.size() - 1);
                // [END_EXCLUDE]
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());

                // A comment has changed, use the key to determine if we are displaying this
                // comment and if so displayed the changed comment.
                Ingredient newIngredient = dataSnapshot.getValue(Ingredient.class);
                String ingredientKey = dataSnapshot.getKey();

                // [START_EXCLUDE]
                int ingredientIndex = mIngredientIds.indexOf(ingredientKey);
                if (ingredientIndex > -1) {
                    // Replace with the new data
                    mIngredients.set(ingredientIndex, newIngredient);

                    // Update the RecyclerView
                    notifyItemChanged(ingredientIndex);
                } else {
                    Log.w(TAG, "onChildChanged:unknown_child:" + ingredientKey);
                }
                // [END_EXCLUDE]
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());

                // A comment has changed, use the key to determine if we are displaying this
                // comment and if so remove it.
                String ingredientKey = dataSnapshot.getKey();

                // [START_EXCLUDE]
                int ingredientIndex = mIngredientIds.indexOf(ingredientKey);
                if (ingredientIndex > -1) {
                    // Remove data from the list
                    mIngredientIds.remove(ingredientIndex);
                    mIngredients.remove(ingredientIndex);

                    // Update the RecyclerView
                    notifyItemRemoved(ingredientIndex);
                } else {
                    Log.w(TAG, "onChildRemoved:unknown_child:" + ingredientKey);
                }
                // [END_EXCLUDE]
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());

                // A comment has changed position, use the key to determine if we are
                // displaying this comment and if so move it.
                Ingredient movedIngredient = dataSnapshot.getValue(Ingredient.class);
                String ingredientKey = dataSnapshot.getKey();

                // ...
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w(TAG, "postComments:onCancelled", databaseError.toException());
                Toast.makeText(mContext, "Failed to load comments.",
                        Toast.LENGTH_SHORT).show();
            }
        };


        ref.addChildEventListener(childEventListener);
        // [END child_event_listener_recycler]

        // Store reference to listener so it can be removed on app stop
        mChildEventListener = childEventListener;

    }

    @NonNull
    @Override
    public IngredientViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.list_item_recipe_ingredient, parent, false);
        return new IngredientViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull IngredientViewHolder holder, int position) {
        Ingredient ingredient = mIngredients.get(position);
        holder.ingred.setText(ingredient.ingredient);
    }

    @Override
    public int getItemCount() {
        return mIngredients.size();
    }

    public class IngredientViewHolder extends RecyclerView.ViewHolder {

        public TextView ingred;

        public IngredientViewHolder(View itemView) {
            super(itemView);

            ingred = itemView.findViewById(R.id.recipe_ingredients_tv);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, "Ingredient: " + mIngredients.get(getAdapterPosition()).ingredient, Toast.LENGTH_SHORT).show();
                }
            });

            itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    Toast.makeText(mContext, "Long Clicked " + getAdapterPosition(), Toast.LENGTH_SHORT).show();

                    return true;
                }
            });
        }
    }

    public void RemoveIngredient(DatabaseReference reference){
        reference.removeValue();
    }

    public void cleanupListener() {
        if (mChildEventListener != null) {
            mDatabaseReference.removeEventListener(mChildEventListener);
        }
    }


}

屏幕截图:

enter image description here enter image description here enter image description here

转到搜索并返回首页

enter image description here

回到家

enter image description here

尝试了Majuran的解决方案(谢谢您),但没有成功。结果相同。将list.clear()方法添加到两个列表中时。

2 个答案:

答案 0 :(得分:1)

据我所知,您的视图中又添加了一件事。当您回到相同的片段对吗? (我在上一个项目中遇到了同样的问题)

问题出在HomeFragment中。相同的值会再次添加到您的这些列表中。

mRecipeList = new ArrayList<>();
mRecipeIds = new ArrayList<>();

在添加侦听器之前先清除它

myRef = database.getReference();

mRecipeList.clear();
mRecipeIds.clear();

myRef.child(Constants.DATABASE_ROOT_FOLLOWING).child(getUid()).add...

希望它有用,编码愉快!

答案 1 :(得分:0)

我能够通过将数据库调用放入适配器的构造函数中来解决此问题。这与Firebase团队在其数据库示例应用程序中放入的示例相同。

相关问题