#java #android #android-recyclerview
Вопрос:
МОЙ ПЕРВОНАЧАЛЬНЫЙ ВОПРОС Я создаю приложение для Android с базой данных firebase в реальном времени. Я получаю сумму узлов firebase в виде бокового переработчика. У меня есть текстовое представление вне представления переработчика, в котором я получаю подсчет значений представления переработчика. МОЯ ПРОБЛЕМА в том, что я не могу получить фактическую сумму, а также сумма продолжает увеличиваться, когда я прокручиваю вверх и вниз. Вот мой основной вид деятельности JAVA-код:
public class MainActivity extends AppCompatActivity {
FirebaseDatabase myfire;
DatabaseReference myRef;
private FirebaseRecyclerOptions<entry> options;
int totalEarned = 0;
int totalSpent = 0;
int totalSaved=0;
@Override
public void onBackPressed() {
final AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Are you sure to exit?");
dialog.setPositiveButton("Play", (dialog1, which) -> {
});
dialog.setNegativeButton("Exit", (dialog12, which) -> {
FirebaseAuth.getInstance().signOut();
MainActivity.this.finish();
});
dialog.show();
}
private String getUID() {
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
if (mUser != null) {
String strUID = mUser.getUid();
if (!TextUtils.isEmpty(strUID)) {
return strUID;
}
}
return "";
}
@SuppressLint("SetTextI18n")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//==============
final RecyclerView userlist = (RecyclerView) findViewById(R.id.idRecycleView);
myfire = FirebaseDatabase.getInstance();
userlist.setLayoutManager(new LinearLayoutManager(this));
//==================
final TextView tvTotalIncome = findViewById(R.id.idTotalIncome);
final TextView tvTotalExpanse = findViewById(R.id.idTotalExpanse);
final TextView tvTotalSaved = findViewById(R.id.idTotalSaved);
//==================
final FloatingActionButton btnBudget = findViewById(R.id.idCreateBudget);
myfire = FirebaseDatabase.getInstance();
final String strUID = getUID();
if (TextUtils.isEmpty(strUID)) {
//handle case of null UID
}
final Intent i = getIntent();
final String month = Objects.requireNonNull(i.getExtras()).getString("Month");
//-------------------------------
btnBudget.setOnClickListener(v -> {
Intent o;
o = new Intent(MainActivity.this, AddBudgetActivity.class);
o.putExtra("Month",month);
startActivity(o);
finish();
});
if (type.equals("Income")) {
try {
totalEarned = (totalEarned sum);
} catch (NumberFormatException ex) {
}
tvTotalIncome.setText("-)" String.valueOf( totalEarned));
holder.btnIcon.setBackgroundResource(R.drawable.circlegreen);
holder.tvEntry.setText("( )" String.valueOf(sum) );
try {
totalSaved = (totalEarned-totalSpent);
} catch (NumberFormatException ex) {
}
tvTotalSaved.setText("(=)" String.valueOf( totalSaved));
}else if (type.equals("Expanse")) {
try {
totalSpent = (totalSpent sum);
} catch (NumberFormatException ex) {
}
tvTotalExpanse.setText("-)" String.valueOf( totalSpent));
holder.btnIcon.setBackgroundResource(R.drawable.circlered);
holder.tvEntry.setText("(-)" String.valueOf(sum) );
try {
totalSaved = (totalEarned-totalSpent);
} catch (NumberFormatException ex) {
}
tvTotalSaved.setText("(=)" String.valueOf( totalSaved));
}else {
Toast.makeText(MainActivity.this, " Something Went Wrong !", Toast.LENGTH_SHORT).show();
}
//======================
myRef = myfire.getReference().child("Data").child(strUID).child(month);
//-------------------------
options = new FirebaseRecyclerOptions.Builder<entry>()
.setQuery(myRef, entry.class)
.build();
final FirebaseRecyclerAdapter<entry, holder_menu> adapter = new FirebaseRecyclerAdapter<entry, holder_menu>(options) {
@Override
protected void onBindViewHolder(@NonNull @NotNull holder_menu holder, final int i, @NonNull @NotNull entry model) {
final String title = getRef(i).getKey();
assert title != null;
myRef = myfire.getReference().child("Data").child(strUID).child(month).child(title).child("Budget");
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
int budget = 0;
if (dataSnapshot.getValue() == null) {
Toast.makeText(getApplicationContext(), "Data Not Available", Toast.LENGTH_LONG).show();
} else {
final String stData1 = (Objects.requireNonNull(dataSnapshot.child("stData1").getValue())).toString();
final String stData2 = (Objects.requireNonNull(dataSnapshot.child("stData2").getValue())).toString();
final String stData3 = (Objects.requireNonNull(dataSnapshot.child("stData3").getValue())).toString();
final String stData4 = (Objects.requireNonNull(dataSnapshot.child("stData4").getValue())).toString();
entry basic = new entry(stData1, stData2, stData3, stData4);
String first = stData2.substring(0, 1);
holder.btnIcon.setText(first);
holder.tvHead.setText(stData2);
String type;
type=(stData3);
holder.tvBudget.setText("@" stData4);
int amount = 0;
//important line
try {
amount = (Integer.parseInt(stData4));
} catch (NumberFormatException ex) {
}
//======================
budget = amount;
myRef = myfire.getReference().child("Data").child(strUID).child(month).child(title).child("Entry");
final int finalBudget = budget;
myRef.addValueEventListener(new ValueEventListener() {
int sum = 0;
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
String section = data.child("stData2").getValue(String.class);
String value = data.child("stData4").getValue(String.class);
assert value != null;
int total = 0;
//important line
try {
total = (Integer.parseInt(value));
} catch (NumberFormatException ex) {
}
//======================
sum = sum total;
//==============
//======================
if (section.equals("Saving")) {
holder.tvHead.setBackgroundColor(getResources().getColor(R.color.saving));
}else if (section.equals("Paying")) {
holder.tvHead.setBackgroundColor(getResources().getColor(R.color.paying));
}else if (section.equals("Using")) {
holder.tvHead.setBackgroundColor(getResources().getColor(R.color.using));
}else if (section.equals("Earning")) {
holder.tvHead.setBackgroundColor(getResources().getColor(R.color.earning));
}else if (section.equals("Taking")) {
holder.tvHead.setBackgroundColor(getResources().getColor(R.color.taking));
}else if (section.equals("Drawing")) {
holder.tvHead.setBackgroundColor(getResources().getColor(R.color.drawing));
}else {
Toast.makeText(MainActivity.this, " Something Went Wrong !", Toast.LENGTH_SHORT).show();
}
}
holder.tvEntry.setText("( )" String.valueOf(sum) );
holder.tvBalance.setText("(=)" String.valueOf(finalBudget - sum) );
//important line
holder.btnView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent o;
o = new Intent(MainActivity.this, ViewHistoryActivity.class);
o.putExtra("Title", title);
o.putExtra("Month", month);
o.putExtra("Type", type);
startActivity(o);
finish();
}
});
holder.btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (type.equals("Income")) {
Intent o;
o = new Intent(MainActivity.this, EntryIncomeActivity.class);
o.putExtra("Title", title);
o.putExtra("Month", month);
o.putExtra("Type", type);
startActivity(o);
finish();
}else if (type.equals("Expanse")) {
Intent o;
o = new Intent(MainActivity.this, EntryExpanseActivity.class);
o.putExtra("Title", title);
o.putExtra("Month", month);
o.putExtra("Type", type);
startActivity(o);
finish();
}else {
Toast.makeText(MainActivity.this, " Something Went Wrong !", Toast.LENGTH_SHORT).show();
}
}
});
if (type.equals("Income")) {
try {
totalEarned = (totalEarned sum);
} catch (NumberFormatException ex) {
}
tvTotalIncome.setText("-)" String.valueOf( totalEarned));
holder.btnIcon.setBackgroundResource(R.drawable.circlegreen);
holder.tvEntry.setText("( )" String.valueOf(sum) );
try {
totalSaved = (totalEarned-totalSpent);
} catch (NumberFormatException ex) {
}
tvTotalSaved.setText("(=)" String.valueOf( totalSaved));
}else if (type.equals("Expanse")) {
try {
totalSpent = (totalSpent sum);
} catch (NumberFormatException ex) {
}
tvTotalExpanse.setText("-)" String.valueOf( totalSpent));
holder.btnIcon.setBackgroundResource(R.drawable.circlered);
holder.tvEntry.setText("(-)" String.valueOf(sum) );
try {
totalSaved = (totalEarned-totalSpent);
} catch (NumberFormatException ex) {
}
tvTotalSaved.setText("(=)" String.valueOf( totalSaved));
}else {
Toast.makeText(MainActivity.this, " Something Went Wrong !", Toast.LENGTH_SHORT).show();
}
//======================
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
throw error.toException(); // never ignore errors
}
});
}
@NonNull
@Override
public holder_menu onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item1, parent, false);
return new holder_menu(v);
}
};
adapter.startListening();
userlist.setAdapter(adapter);
}
}
ОТРЕДАКТИРОВАННЫЙ ВОПРОС В соответствии с предложением @androidLearner
ОСНОВНАЯ ДЕЯТЕЛЬНОСТЬ
public class MainActivity extends AppCompatActivity {
FirebaseDatabase myfire;
DatabaseReference myRef;
int totalEarned = 0;
int totalSpent = 0;
int totalSaved=0;
madapter adapter;
String iconsData;
String headsData;
int budgetsData=0;
int enteriesData=0;
int balancesData=0;
@Override
public void onBackPressed() {
final AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Are you sure to exit?");
dialog.setPositiveButton("Play", (dialog1, which) -> {
});
dialog.setNegativeButton("Exit", (dialog12, which) -> {
FirebaseAuth.getInstance().signOut();
MainActivity.this.finish();
});
dialog.show();
}
private String getUID() {
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
if (mUser != null) {
String strUID = mUser.getUid();
if (!TextUtils.isEmpty(strUID)) {
return strUID;
}
}
return "";
}
@RequiresApi(api = Build.VERSION_CODES.N)
@SuppressLint("SetTextI18n")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//==============
final RecyclerView userlist = (RecyclerView) findViewById(R.id.idRecycleView);
myfire = FirebaseDatabase.getInstance();
userlist.setLayoutManager(new LinearLayoutManager(this));
//==================
final TextView tvTotalIncome = findViewById(R.id.idTotalIncome);
final TextView tvTotalExpanse = findViewById(R.id.idTotalExpanse);
final TextView tvTotalSaved = findViewById(R.id.idTotalSaved);
//==================
final FloatingActionButton btnBudget = findViewById(R.id.idCreateBudget);
myfire = FirebaseDatabase.getInstance();
final String strUID = getUID();
if (TextUtils.isEmpty(strUID)) {
//handle case of null UID
}
final Intent i = getIntent();
final String month = Objects.requireNonNull(i.getExtras()).getString("Month");
//-------------------------------
btnBudget.setOnClickListener(v -> {
Intent o;
o = new Intent(MainActivity.this, AddBudgetActivity.class);
o.putExtra("Month",month);
startActivity(o);
finish();
});
//amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;---new method
myRef = myfire.getReference().child("Data").child(strUID).child(month);
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
String title = dataSnapshot.getKey();
assert title != null;
myRef = myfire.getReference().child("Data").child(strUID).child(month).child(title).child("Budget");
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
Toast.makeText(getApplicationContext(), "Data Not Available", Toast.LENGTH_LONG).show();
} else {
final String stData1 = (Objects.requireNonNull(dataSnapshot.child("stData1").getValue())).toString();
final String stData2 = (Objects.requireNonNull(dataSnapshot.child("stData2").getValue())).toString();
final String stData3 = (Objects.requireNonNull(dataSnapshot.child("stData3").getValue())).toString();
final String stData4 = (Objects.requireNonNull(dataSnapshot.child("stData4").getValue())).toString();
entry basic = new entry(stData1, stData2, stData3, stData4);
iconsData = stData2.substring(0, 1);
headsData=stData2;
//---------------------------------------------------------------------------entry
myRef = myfire.getReference().child("Data").child(strUID).child(month).child(title).child("Entry");
myRef.addValueEventListener(new ValueEventListener() {
int sum = 0;
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
String section = data.child("stData2").getValue(String.class);
String value = data.child("stData4").getValue(String.class);
assert value != null;
int total = 0;
try {
total=(Integer.parseInt(value));
} catch (NumberFormatException ex) {
}
//==============
sum=sum total;
}
enteriesData=sum;
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
throw error.toException(); // never ignore errors
}
});
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
//amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;------NewMethod
balancesData=budgetsData-enteriesData;
ArrayList<String> iconList = new ArrayList<>();
iconList.add(iconsData);
ArrayList<String> headList= new ArrayList<>();
headList.add(headsData);
ArrayList<Integer> budgetList = new ArrayList<>();
budgetList.add(budgetsData);
ArrayList<Integer> entryList = new ArrayList<>();
entryList.add(enteriesData);
ArrayList<Integer> balanceList = new ArrayList<>();
balanceList.add(balancesData);
adapter = new madapter ( this, iconList,headList,budgetList,entryList,balanceList);
userlist.setAdapter(adapter);
}
}
RECYCLER VIEW Adapter
public class madapter extends RecyclerView.Adapter<madapter.ViewHolder> {
private List<String> stricon;
private List<String> strhead;
private List<Integer> intbudget;
private List<Integer> intentry;
private List<Integer> intbalance;
//---
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
public madapter(MainActivity mainActivity, ArrayList<String> iconList, ArrayList<String> headList, ArrayList<Integer> budgetList, ArrayList<Integer> entryList, ArrayList<Integer> balanceList) {
this.mInflater = LayoutInflater.from(mainActivity);
this.stricon = iconList;
this.strhead = headList;
this.intbudget = budgetList;
this.intentry = entryList;
this.intbalance= balanceList;
}
// inflates the row layout from xml when needed
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.item1, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
String icons = stricon.get(position);
String heads = strhead.get(position);
int budgets = intbudget.get(position);
int entries = intentry.get(position);
int balances = intbalance.get(position);
holder.btnIcon.setText(icons);
holder.tvHead.setText(heads);
holder.tvBudget.setText(String.valueOf(budgets));
holder.tvEntry.setText(String.valueOf(entries));
holder.tvBalance.setText(String.valueOf(balances));
}
// total number of rows
@Override
public int getItemCount() {
return stricon.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public Button btnIcon;
public TextView tvHead;
public TextView tvBudget;
public TextView tvEntry;
public TextView tvBalance;
public Button btnView;
public Button btnAdd;
ViewHolder(View itemView) {
super(itemView);
btnIcon= (Button) itemView.findViewById(R.id.idIcon);
tvHead = (TextView) itemView.findViewById(R.id.idHead);
tvBudget = (TextView) itemView.findViewById(R.id.idBudget);
tvEntry = (TextView) itemView.findViewById(R.id.idEntry);
tvBalance = (TextView) itemView.findViewById(R.id.idBalance);
btnView= (Button) itemView.findViewById(R.id.idView);
btnAdd = (Button) itemView.findViewById(R.id.idAdd);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
String getItem(int id) {
return stricon.get(id);
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
НОВАЯ ПРОБЛЕМА ПОСЛЕ РЕДАКТИРОВАНИЯ
Я не могу получить какие-либо данные из firebase в свой список массивов методом datasnapshot. Но да, в моем представлении переработчика отображаются данные, если я добавляю текст или цифры в свой список вручную.
Это отчет о крушении
2021-05-24 00:07:12.368 19933-19933/com.myappname E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myappname, PID: 19933
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.get(ArrayList.java:437)
at com.myappname.model.rvAdapter.onBindViewHolder(mAdapter.java:54)
at com.myappname.model.rvAdapter.onBindViewHolder(mAdapter.java:16)2021-05-24 .......................................
Комментарии:
1. Похоже, вы не понимаете структуру держателей представлений: они представляют только элемент из вашего набора данных и никоим образом не должны хранить что-либо, кроме изменчивого состояния представления, так как во время прокрутки они будут переработаны и использованы для отображения (привязки) другого элемента. Это означает, что элементы, которые находятся «вне поля зрения», не будут иметь привязанного к ним держателя просмотра, поэтому вы также не сможете их «получить».
2. сумма продолжает увеличиваться, потому что каждый раз, когда onBindViewHolder получает значение от firebase при прокрутке вверх и вниз. Поэтому переместите все методы обратного вызова firebase из onBindViewHolder в свою активность, затем из активности получите значения из firebase, а затем установите адаптер recyclerview. затем получите фактическую сумму.
3. Пожалуйста, обновите свой вопрос с помощью разделенных функций mainActivty и recycllerviewAdapter.
4. итак, вам нужно общее количество предметов в представлении переработчика?
5. вы почти закончили. все еще продолжаете расти?
Ответ №1:
установите адаптер после получения данных с firebase
myRef.addValueEventListener(new ValueEventListener() {
int sum = 0;
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()) {
String section = data.child("stData2").getValue(String.class);
String value = data.child("stData4").getValue(String.class);
assert value != null;
int total = 0;
//==============
sum=sum total;
}
enteriesData=sum;
//Send your data to adapter as per your need from here
adapter = new madapter ( this, iconList,headList,budgetList,entryList,balanceList);
userlist.setAdapter(adapter);
}
Комментарии:
1. спрашиваю о каком из них ? @пользователь14253444
2. я не уверен в том, что такое balenceList.если balenceList содержит balancesData ,переместите эту логику(balancesData=budgetsData-enteriesData) в метод onDataChange (). Примечание:выполняйте все свои вычисления внутри onDataChange().@user14253444
3. например ,у вас размер массива 2, при попытке получить значение(2) возникнет исключение IndexOutOfBoundsException.потому что на 3-м месте ничего нет. @пользователь14253444