I have a MachineActivity. It has cardViews with an icon and text. So I have stored the names of the cardView in firebase database and the icons are stored in firebase storage. The cardView is custom and hence the adapter. Below is my Machine class and the MachineAdapter for cardView.
Machine.java
package com.example.tbiapphome;
import com.google.firebase.storage.StorageReference;
public class Machine {
String machineName;
StorageReference machineIcon;
public Machine(String machineName, StorageReference machineIcon) {
this.machineName = machineName;
this.machineIcon = machineIcon;
}
public String getMachineName() {
return machineName;
}
public StorageReference getMachineIcon() {
return machineIcon;
}
public void setMachineName(String machineName) {
this.machineName = machineName;
}
public void setMachineIcon(StorageReference machineIcon) {
this.machineIcon = machineIcon;
}
}
MachineAdapter.java
package com.example.tbiapphome;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.List;
import br.com.sapereaude.maskedEditText.MaskedEditText;
public class MachineAdapter extends RecyclerView.Adapter<MachineAdapter.MyViewHolder> {
private Context mContext;
private List<Machine> machineList;
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView machineCardName;
public ImageView overflow, machineCardImageView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
machineCardName = itemView.findViewById(R.id.machineCardName);
machineCardImageView = itemView.findViewById(R.id.machineCardImageView);
overflow = (ImageView) itemView.findViewById(R.id.overflow);
}
}//myViewHolder class ended
public MachineAdapter(Context mContext, List<Machine> machineList) {
this.mContext = mContext;
this.machineList = machineList;
}
@NonNull
@Override
public MachineAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.machine_card, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull final MachineAdapter.MyViewHolder holder, int position) {
Machine machine = machineList.get(position);
holder.machineCardName.setText(machine.getMachineName());
// loading machine icons using Glide library
Glide.with(mContext).load(machine.getMachineIcon()).into(holder.machineCardImageView);
holder.overflow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showPopupMenu(holder.overflow);
}
});
}
/**
* Showing popup menu when tapping on 3 dots
*/
private void showPopupMenu(View view) {
// inflate menu
PopupMenu popup = new PopupMenu(mContext, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_machine, popup.getMenu());
popup.setOnMenuItemClickListener(new MyMenuItemClickListener());
popup.show();
}
/**
* Click listener for popup menu items
*/
class MyMenuItemClickListener implements PopupMenu.OnMenuItemClickListener {
public MyMenuItemClickListener() {
}
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.book:
//setting up popup for register item
//setting machines array for spinner
final String[] machinesArray = {"Choose a Machine...", "CNC Machine", "Drill Machine", "Screwdriver", "Contact"," Demo1", "Demo2", "Demo3", "Demo4", "Demo5"};
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(R.layout.request_dialog, null);
final MaskedEditText dateEditText = view.findViewById(R.id.dateEditText);
final MaskedEditText startTimeEditText = view.findViewById(R.id.startTimeEditText);
final MaskedEditText endTimeEditText = view.findViewById(R.id.endTimeEditText);
builder.setTitle("Create request");
final Spinner spinner = view.findViewById(R.id.spinner);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, machinesArray);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(arrayAdapter);
builder.setPositiveButton("Book", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (spinner.getSelectedItem().toString().equalsIgnoreCase("")){
Toast.makeText(mContext, "Choose a machine", Toast.LENGTH_SHORT).show();
}
if (dateEditText.getRawText().equalsIgnoreCase("")) {
Toast.makeText(mContext, "Enter date", Toast.LENGTH_SHORT).show();
}
if (startTimeEditText.getRawText().equalsIgnoreCase("") || endTimeEditText.getRawText().equalsIgnoreCase("")){
Toast.makeText(mContext, "Enter time", Toast.LENGTH_SHORT).show();
}
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setView(view);
AlertDialog alertDialog = builder.create();
alertDialog.show();
return true;
default:
}
return false;
}
}
@Override
public int getItemCount() {
return machineList.size();
}
}
MachineActivit.java codeblock for cardView
private void prepareMachineIcons() {
final int[] count = {0};
//querying the database
//Using two array to store the name and iconurl
DatabaseReference mDatabase;
mDatabase = FirebaseDatabase.getInstance().getReference();
Query machines = mDatabase.child("Machines");
machines.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
count[0]++;
String name = dataSnapshot.child("name").getValue().toString();
StorageReference storageReference = FirebaseStorage.getInstance().getReference();
String imagePath = "machine images/m"+String.valueOf(count)+".jpg";
StorageReference iconPathReference = storageReference.child(imagePath);
//updating machine UI
Machine a;
a = new Machine(name, iconPathReference);
machineList.add(a);
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
The error comes like this
2020-05-21 22:27:30.154 10397-10397/com.example.tbiapphome E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tbiapphome, PID: 10397
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
at com.example.tbiapphome.MachineActivity$2.onDataChange(MachineActivity.java:99)
at com.google.firebase.database.Query$1.onDataChange(com.google.firebase:firebase-database@@19.3.0:179)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.3.0:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.3.0:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.3.0:55)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Here both the cardView text and image are fetched inside the addEventChildListener. The image is fetched using glide . But my problem here is that I can't get this code working because the cardViewtext and image are fetched at different times. The text loads faster than the image. Hence this code raises an exception. Is there any way I make make it such that the image is fetched after the text or Is there any way to do a task after a query is completed like we do in parse. Please help