As we know there is no multi query option to firebase realtime database, so instead of using default FirebaseRecycler methods I am trying to manually feed keys from arraylist to the recycler view. In order to sort specific keys on the basis specific child nodes of the given parent I wrote below logic.
If I try to individually log the keys in if statement it shows displays all the sorted keys.
But now my problem is whenever I try to log the arraylist after fetching the values it shows null and if I log specific value at some index below error shows up.
public class categorizedProducts extends AppCompatActivity { private String catKey; private DatabaseReference productRef, catRef; private ArrayList<String> keyVal = new ArrayList<>(); private long count = 0; private long i = 0; private void queryLogic(final String catTitle) { productRef.orderByChild("count").addValueEventListener(new ValueEventListener() { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { count = dataSnapshot.getChildrenCount(); for (final DataSnapshot snap: dataSnapshot.getChildren()){ productRef.child(Objects.requireNonNull(snap.getKey())).addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { if (Objects.requireNonNull(dataSnapshot.child("category").getValue()).toString().equals(catTitle)) { //keyVals.add(snap.getKey()); keyVal.add(snap.getKey()); i++; } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } // I am trying to log my arraylist here after retrieving the required keys from database }
2020-06-27 19:50:32.315 567-567/com.kalpana.mortoys E/AndroidRuntime: FATAL EXCEPTION: main Process: com.kalpana.mortoys, PID: 567 java.lang.IndexOutOfBoundsException: Index: 1, Size: 0 at java.util.ArrayList.get(ArrayList.java:437) at com.kalpana.mortoys.categorizedProducts$1.onDataChange(categorizedProducts.java:65) at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.2.1:75) at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.2.1:63) at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.2.1:55) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7397) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
I temporarily solved my error using this
public class categorizedProducts extends AppCompatActivity { private String catKey; private DatabaseReference productRef, catRef; private ArrayList<String> keyVal = new ArrayList<>(); private long count = 0, i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_categorized_products); initFields(); try { Bundle bundle = getIntent().getExtras(); assert bundle != null; catKey = bundle.getString("key"); assert catKey != null; catRef.child(catKey).addValueEventListener(new ValueEventListener() { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { queryLogic(Objects.requireNonNull(dataSnapshot.child("catTitle").getValue()).toString()); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } catch (NullPointerException e) { e.printStackTrace(); } } private void initFields() { productRef = FirebaseDatabase.getInstance().getReference().child("products"); catRef = FirebaseDatabase.getInstance().getReference().child("categories"); } @Override protected void onStart() { super.onStart(); if (i == count) { new Handler().postDelayed(new Runnable() { @Override public void run() { Log.i("TAG", "onStart: " + keyVal); } }, 3000); } } private void queryLogic(final String catTitle) { productRef.orderByChild("count").addValueEventListener(new ValueEventListener() { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { count = dataSnapshot.getChildrenCount(); for (final DataSnapshot snap: dataSnapshot.getChildren()){ i++; productRef.child(Objects.requireNonNull(snap.getKey())).addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { if (Objects.requireNonNull(dataSnapshot.child("category").getValue()).toString().equals(catTitle)) { //keyVals.add(snap.getKey()); keyVal.add(snap.getKey()); //Log.i("TAG", "onDataChange: " + i); } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } }
but still need an perfect solution
Advertisement
Answer
You could use a callback interface:
interface CallBack {public void done()}
and call queryLogic()
as
queryLogic(catTitle,new CallBack() { public void done() { //log your arrayList here } }); private void queryLogic (final String catTitle,final CallBack callBack){..}
and after the iteration is over just call the method callBack.done()
.