如何使用Firebase数据在recyclerView中获取商品数?

时间:2019-04-11 00:46:40

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

我创建一个带有一系列CardView的RecyclerView。我的最终目标是能够由于Firebase数据库调用的时间而在活动中更改单个CardView内部的文本。我现在的问题是,如何获得RecyclerView中的物品数量?

我知道大多数人会将我引向Adapter.getItemCount()方法。但是,由于适配器似乎尚未创建,此刻仅返回零。我认为,这个问题更多地是与代码运行时间有关的。

活动类别:

package com.cmsc355.forfit;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.cmsc355.forfit.util.exerciseAdapterClass;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;
import java.util.HashMap;

public class ChallengeView extends AppCompatActivity {

    public static Context context;
    public static String cCESnapshot;

    //Variables
    String team;
    HashMap<String, String> currChallenges;
    ArrayList<String> subAthletes;
    ArrayList<String> exerciseList;
    ArrayList<String> teamMem;

    //System
    private Intent intent;
    public static String cName;

    //XML
    private TextView name;
    private TextView startDateTV;
    private TextView endDateTV;
    private TextView description;
    private Button bSubscribe;
    private Button bDropout;

    private ProgressBar difficulty;

    //Exercise List
    private RecyclerView exerciseRecyclerView;
    private RecyclerView.Adapter exerciseAdapter;
    private RecyclerView.LayoutManager exerciselayoutManager;

    //Database
    DatabaseReference databaseReferenceChallenge;
    DatabaseReference databaseReferenceAthlete;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //Initial setup of activity
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_challenge_view);

        ChallengeView.context = getApplicationContext();

        //variable list
        currChallenges = new HashMap<>();
        subAthletes = new ArrayList<>();
        exerciseList = new ArrayList<>();
        teamMem = new ArrayList<>();

        //system references
        intent = getIntent();
        cName = intent.getStringExtra("name");
        //cCESnapshot = intent.getStringExtra("snapshot");
        //System.out.println(cCESnapshot);

        //Authentication references
        FirebaseAuth mAuth = FirebaseAuth.getInstance();
        FirebaseUser user = mAuth.getCurrentUser();

        final String uid = user.getUid();

        //XML references
        name = findViewById(R.id.ChallengeName);
        startDateTV = findViewById(R.id.DurationTextStart);
        endDateTV = findViewById(R.id.DurationTextEnd);
        description = findViewById(R.id.DescriptionText);
        difficulty = findViewById(R.id.difficultyBar);

        bSubscribe = findViewById(R.id.BSignUp);
        bDropout = findViewById(R.id.CV_DropOut);

        //Exercise List
        exerciseRecyclerView = findViewById(R.id.ExerciseView);
        exerciseRecyclerView.setHasFixedSize(true);

        exerciselayoutManager = new LinearLayoutManager(this);
        exerciseRecyclerView.setLayoutManager(exerciselayoutManager);

        exerciseAdapter = new exerciseAdapterClass(exerciseList);
        exerciseRecyclerView.setAdapter(exerciseAdapter);
        exerciseAdapter.notifyDataSetChanged();


        //database references
        databaseReferenceChallenge = FirebaseDatabase.getInstance().getReference("Challenges");
        databaseReferenceAthlete = FirebaseDatabase.getInstance().getReference("Athlete Users");



        //Initial population of views and variables
        databaseReferenceChallenge.addValueEventListener(new ValueEventListener() {
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                DataSnapshot da = dataSnapshot.child(cName);

                String dateStart = da.child("StartDate").child("day").getValue() + "/" + da.child("StartDate").child("month").getValue()+ "/" + da.child("StartDate").child("year").getValue();
                String dateEnd = da.child("EndDate").child("day").getValue() + "/" + da.child("EndDate").child("month").getValue()+ "/" + da.child("EndDate").child("year").getValue();


                long diff = (long)da.child("difficulty").getValue();
                int tDifficulty = (int)diff;

                name.setText((String)da.child("name").getValue());
                startDateTV.setText(dateStart);
                endDateTV.setText(dateEnd);
                description.setText((String)da.child("description").getValue());
                difficulty.setMin(1);
                difficulty.setMax(5);
                difficulty.setProgress(tDifficulty);


                for(DataSnapshot ex : da.child("exercises").getChildren()){
                    exerciseList.add((String)ex.getValue());
                }

            }

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

            }
        });

        //***************************************************************************************************************************************\\
        //This should be grabbing all the challenges that the athlete is currently subscribed to.
        databaseReferenceAthlete.addListenerForSingleValueEvent(new ValueEventListener(){
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                DataSnapshot dataSnapshot1 = dataSnapshot.child(uid).child("currChallenges");
                HashMap<String, String> currChallengesT = (HashMap<String, String>) dataSnapshot1.getValue();
                currChallenges.clear();
                if(currChallengesT != null) {
                    currChallenges.putAll(currChallengesT);
                    if(currChallenges.containsKey(cName)) {
                        bSubscribe.setVisibility(View.GONE);
                        bDropout.setVisibility(View.VISIBLE);
                    }
                    else{
                        bSubscribe.setVisibility(View.VISIBLE);
                        bDropout.setVisibility(View.GONE);
                    }
                }
                else{
                    bSubscribe.setVisibility(View.VISIBLE);
                    bDropout.setVisibility(View.GONE);
                }
            }
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {}
        });
        //***************************************************************************************************************************************\\

        //***************************************************************************************************************************************\\
        //This should be grabbing all the athletes subscribed to the challenge.
        databaseReferenceChallenge.addListenerForSingleValueEvent(new ValueEventListener(){
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                DataSnapshot dataSnapshot1 = dataSnapshot.child(cName).child("subscribedAthletes");
                ArrayList<String> subAthletesT = (ArrayList<String>) dataSnapshot1.getValue();
                if(subAthletesT != null) {
                    subAthletes.addAll(subAthletesT);
                }
            }
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {}
        });
        //***************************************************************************************************************************************\\

        databaseReferenceAthlete.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                DataSnapshot dataSnapshot1 = dataSnapshot.child(uid).child("currChallenges").child(cName).child("team");
                team = (String) dataSnapshot1.getValue();
            }

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

            }
        });
    }

    @Override
    protected void onStart(){
        super.onStart();


        //This is where I try to call the Recycler View.

        System.out.println(exerciseList.size());

        for(int i = 0; i < exerciseAdapter.getItemCount(); i ++){
            System.out.println("Inside for loop: " + i);
            CardView thing = (CardView) exerciselayoutManager.getChildAt(i);
            exerciseAdapterClass.exerciseViewHolder holder = (exerciseAdapterClass.exerciseViewHolder) exerciseRecyclerView.getChildViewHolder(thing);
            System.out.println("\n\n==============================================================\n" + holder.amount.getText().toString() +
                    "\n==============================================================");
        }

    }

    public static Context getAppContext() {
        return ChallengeView.context;
    }

    /*
    Calls for the transfer to the challenge signup activity
     */
    public void Subscribe(View view){
        Intent intent = new Intent (this, ChallengeSignUp.class);
        intent.putExtra("name", cName);
        startActivity(intent);

    }
}

适配器类:

package com.cmsc355.forfit.util;

import android.support.annotation.NonNull;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.cmsc355.forfit.ChallengeView;
import com.cmsc355.forfit.R;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;

public class exerciseAdapterClass extends RecyclerView.Adapter<exerciseAdapterClass.exerciseViewHolder>{

    ArrayList<String> exerciseList;

    public static class exerciseViewHolder extends RecyclerView.ViewHolder {
        public CardView cardView;
        public TextView exerciseName;
        public TextView amount;
        public EditText inputAmount;
        public Button bEnter;

        DatabaseReference databaseReferenceChallenge;
        DatabaseReference databaseReferenceAthlete;

        int currDone;



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

            //Variables
            currDone = 0;

            //Authentication
            FirebaseAuth mAuth = FirebaseAuth.getInstance();
            FirebaseUser user = mAuth.getCurrentUser();
            final String uid = user.getUid();

            //Database Reference
            databaseReferenceChallenge = FirebaseDatabase.getInstance().getReference("Challenges");
            databaseReferenceAthlete = FirebaseDatabase.getInstance().getReference("Athlete Users");

            //XML
            cardView = itemView.findViewById(R.id.cv_cardView);
            exerciseName = itemView.findViewById(R.id.cv_exerciseName);
            amount = itemView.findViewById(R.id.cv_amount);
            inputAmount = itemView.findViewById(R.id.cv_input);
            bEnter = itemView.findViewById(R.id.cv_button);

            bEnter.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(!(inputAmount.getText().toString().trim().length() == 0)){
                        int input = Integer.parseInt(inputAmount.getText().toString());
                        final String cName = ChallengeView.cName;

                        databaseReferenceAthlete.addValueEventListener(new ValueEventListener() {
                            @Override
                            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                try{
                                    DataSnapshot snapshot = dataSnapshot.child(uid).child("currChallenges").child(cName).child(exerciseName.getText().toString());
                                    currDone = (int)((long)snapshot.getValue());
                                }
                                catch(Exception e){
                                    e.printStackTrace();
                                }
                            }

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

                        currDone += input;
                        databaseReferenceAthlete.child(uid).child("currChallenges").child(cName).child(exerciseName.getText().toString()).setValue(currDone);

                    }
                    else{
                        Toast.makeText(ChallengeView.getAppContext(), "Nothing in there.", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    }

    public exerciseAdapterClass(ArrayList<String> inputList){
        exerciseList = inputList;
    }

    @Override
    public int getItemCount() {

        return exerciseList.size();
    }

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

    @Override
    public void onBindViewHolder(final exerciseViewHolder holder, final int i) {
        holder.setIsRecyclable(false);

        String s1 = exerciseList.get(i);

        //Possible error if the name contains "Amount"
        final String name = s1.substring(0, s1.indexOf("Amount")-1); //first section of the string to give the name.

        String s2 = s1.substring(s1.indexOf(": ")); //cuts of the front of the string and puts to a new substring.

        String a = s2.substring(s2.indexOf(' '), s2.indexOf("\n")); //cuts the part after the : but before the \n
        a = a.trim(); //trims the inevitable white space
        final String units = a.substring(a.indexOf(' ')); //gets the units off the string
        a = a.substring(0, a.indexOf(' ')); //cuts off the units
        final int amount = Integer.parseInt(a); //parse to use as a number

        String s3 = s2.substring(s2.indexOf("\n")); //cuts to the date and new string
        s3 = s3.substring(8); //removes the date tag

        String y = s3.substring(0, s3.indexOf('/')); //cuts year into new string
        final int year = Integer.parseInt(y); //parse year to use as a number

        s3 = s3.substring(s3.indexOf('/') + 1); //cuts year off

        String d = s3.substring(0, s3.indexOf('/')); //cuts day into new string
        final int day = Integer.parseInt(d); //parse day

        s3 = s3.substring(s3.indexOf('/') + 1); //cuts day off
        final int month = Integer.parseInt(s3); //parses month

        /*DatabaseReference databaseReferenceAthlete = FirebaseDatabase.getInstance().getReference("Athlete Users");
        databaseReferenceAthlete.addValueEventListener(new ValueEventListener() {

            FirebaseAuth mAuth = FirebaseAuth.getInstance();
            FirebaseUser user = mAuth.getCurrentUser();
            final String uid = user.getUid();

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

                DataSnapshot snapshot = dataSnapshot.child(uid).child("currChallenges").child(ChallengeView.cName).child(name);
                try{
                    int val = ((int)((long)snapshot.getValue()));


                    int printVal = Math.max(0, amount - val);



                }
                catch(Exception e){}
            }

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

            }
        });*/
        holder.amount.setText("0" + units);
        holder.exerciseName.setText(name);
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }
}

截至目前,当我尝试调用引用RecyclerView的任何内容时,它返回0或null。我的想法是,尚未启动用于启动RecyclerView的代码。

1 个答案:

答案 0 :(得分:0)

您所做的是: 在适配器类中,您尝试检索Firebase数据。 到返回数据时,构造函数已被调用,列表exerciseList的大小为零。另外要注意的是,您在ViewHolder类中提到了Firebase调用(该操作在后台运行)。

执行此操作的最佳方法是: 首先,您从适配器外部的Firebase获取数据,然后设置适配器。喜欢 在MainActivity中执行后台作业(以从Firebase检索数据),然后在成功检索之后,将适配器设置为

exerciseAdapterClass adapter = new Adapter (exerciseList);
recyclerView.setAdapter(adapter);

如果您要在Firebase数据中发生某些更改时通知回收者视图,可以执行以下操作:

使用以下方法从Firebase获取更改的列表(exerciseList)或更改的项目(String

databaseReferenceAthlete.addValueEventListener 

databaseReferenceAthlete.addChildEventListener

然后

adapter.update(exerciseList);
adapter.notifyDatasetChanged;

adapter.update(newString);
adapter.notifyItemChanged(position)

*注意:您必须在适配器类中设置更新方法

示例: 适配器更新列表

public class NoteListAdapter extends RecyclerView.Adapter<NoteListAdapter.NoteViewHolder> {

private List<String> list;

public NoteListAdapter(List<String> list) {
    this.list = list;
}

public void update(List<String> list){
    this.list = list;
}

@NonNull
@Override
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
    Context context = parent.getContext();
    LayoutInflater inflater = LayoutInflater.from(context);
    View noteView = inflater.inflate(R.layout.item_note, parent, false);

    return new NoteViewHolder(noteView);
}

@Override
public void onBindViewHolder(@NonNull NoteViewHolder holder, int i) {
    String itemString = list.get(i);
    holder.textView.setText(itemString);
}

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

public class NoteViewHolder extends RecyclerView.ViewHolder{
    private TextView textView;

    public NoteViewHolder(@NonNull View itemView) {
        super(itemView);
        textView = itemView.findViewById(R.id.text_rv);
    }
}
}

在mainActivity中:

public class NotesActivity extends AppCompatActivity implements NotesContract.View{

private TextView textView;
private Button add;
private NotesContract.UserActionsListener mActionsListener;
private NoteRepository repository;

private RecyclerView recyclerView;
private NoteListAdapter adapter;
List<String> list = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textView = findViewById(R.id.text_view);
    add = findViewById(R.id.button);
    repository = new NoteRepository();
    recyclerView = findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    adapter = new NoteListAdapter(list);
    recyclerView.setAdapter(adapter);



    mActionsListener = new NotePresenter(repository,this);
    add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            mActionsListener.loadNotes("hello");
        }
    });
}

@Override
public void showAddNote(List<String> data) {
    String line = "";
    for(String s:data){
        line = line.concat(s);

    }
    textView.setText(line);
}

@Override
public void showRecViewNote(List<String> data) {
    adapter.update(data);
    adapter.notifyDataSetChanged();


}
}

看看,如何设置回收者视图

recyclerView = findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    adapter = new NoteListAdapter(list);
    recyclerView.setAdapter(adapter);

以及如何通知

public void showRecViewNote(List<String> data) {
    adapter.update(data);
    adapter.notifyDataSetChanged();


}