我创建一个带有一系列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的代码。
答案 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();
}