In meiner Anwendung habe ich einen Abschnitt (Fragment), wo ich die Pflanzen und ihre Mengen (in Firebase gespeichert) durch eine ListView zeigen möchte. Mit einem Floating-Aktion-Button erlaube ich, die Menge zu aktualisieren, die sich auf eine Pflanze bezieht, wenn sie bereits in der Datenbank ist, andernfalls, um sie hinzuzufügen.ListView und benutzerdefinierter Adapter mit Firebase
Hier meine ersten zwei Probleme:
# 1 Dieses Fragment wird in der Haupt-Aktivität gezeigt, so beim Start Ich mag würde, dass die aus der Datenbank abgerufenen Daten werden sofort angezeigt, aber das doesn‘ t geschehen, sie werden nur angezeigt, nachdem eine Anlage hinzugefügt/aktualisiert wurde.
# 2 Hier ist mein Code:
public class MyVegGardenFragment extends Fragment {
private View v;
private ListView listView;
private DatabaseReference database;
private FirebaseAuth auth;
private FirebaseUser us;
private Map<String, Integer> myVegGarden;
private ArrayList<String> plantsList = new ArrayList<>();
private ArrayList<Integer> quantityList = new ArrayList<>();
private MyVegGardenAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myVegGarden = new HashMap<>();
database = FirebaseDatabase.getInstance().getReference();
auth = FirebaseAuth.getInstance();
us = auth.getCurrentUser();
database.addValueEventListener(new ValueEventListener() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User u = dataSnapshot.child("users").child(us.getUid()).getValue(User.class);
if (u != null) {
myVegGarden = u.getMyVegGarden();
if (myVegGarden != null) {
for(Map.Entry<String, Integer> entry : myVegGarden.entrySet()) {
plantsList.add(entry.getKey());
quantityList.add(entry.getValue());
}
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
v = inflater.inflate(R.layout.myveggarden_fragment_layout, container, false);
listView = (ListView) v.findViewById(R.id.myVegGarden_list_view);
adapter = new MyVegGardenAdapter(getActivity(), plantsList, quantityList);
listView.setAdapter(adapter);
FloatingActionButton fab = (FloatingActionButton) v.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder;
// [...] leaving code for AlertDialog working correctly
builder.setPositiveButton("PLANT", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final String plant = options[plant_picker.getValue()];
final int quantity = quantity_picker.getValue();
if(!adapter.getPlantsList().contains(plant)){
adapter.add(plant, quantity);
}
else {
adapter.updateIfPresent(plant, quantity);
}
//update db value
database.addValueEventListener(new ValueEventListener() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
User u = dataSnapshot.child("users").child(us.getUid()).getValue(User.class);
if (u != null) {
myVegGarden = u.getMyVegGarden();
if (myVegGarden != null) {
myVegGarden.put(plant, quantity);
}
else {
myVegGarden = new HashMap<>();
myVegGarden.put(plant, quantity);
}
database.child("users").child(us.getUid()).child("myVegGarden").setValue(myVegGarden);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
dialog.dismiss();
}
});
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
} });
AlertDialog dialog = builder.create();
dialog.show();
}
});
return v;
}
}
public class MyVegGardenAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private ArrayList<String> dataSource;
private ArrayList<Integer> quantity;
public MyVegGardenAdapter(Context context, ArrayList<String> items, ArrayList<Integer> quantity) {
this.context = context;
dataSource = items;
this.quantity = quantity;
//line 31
inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void add(String plant, Integer qty) {
dataSource.add(plant);
quantity.add(qty);
notifyDataSetChanged();
}
public void updateIfPresent(String plant, Integer qty) {
quantity.set(dataSource.indexOf(plant), qty);
notifyDataSetChanged();
}
public List<String> getPlantsList() { return dataSource; }
@Override
public int getCount() {
return dataSource.size();
}
@Override
public Object getItem(int position) {
return dataSource.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public Object getQuantity(int position) {
return quantity.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get view for row item
View rowView = inflater.inflate(R.layout.listview_row, parent, false);
// Get title element
TextView firstLine = (TextView) rowView.findViewById(R.id.firstLine);
// Get subtitle element
TextView secondLine = (TextView) rowView.findViewById(R.id.secondLine);
// Get icon element
ImageView icon = (ImageView) rowView.findViewById(R.id.list_icon);
String plant = (String) getItem(position);
Integer quantity = (Integer) getQuantity(position);
firstLine.setText(plant);
secondLine.setText(Html.fromHtml("<b>Quantity: </b>" + quantity));
switch(plant) {
case "Bean":
icon.setImageResource(R.drawable.ic_bean_48dp); break;
case "Cabbage":
icon.setImageResource(R.drawable.ic_cabbage_48dp); break;
case "Carrot":
icon.setImageResource(R.drawable.ic_carrot_48dp); break;
case "Cucumber":
icon.setImageResource(R.drawable.ic_cucumber_48dp); break;
case "Eggplant":
icon.setImageResource(R.drawable.ic_eggplant_48dp); break;
case "Lettuce":
icon.setImageResource(R.drawable.ic_lettuce_48dp); break;
case "Pea":
icon.setImageResource(R.drawable.ic_pea_48dp); break;
case "Pepper":
icon.setImageResource(R.drawable.ic_pepper_48dp); break;
case "Radish":
icon.setImageResource(R.drawable.ic_radish_48dp); break;
case "Tomato":
icon.setImageResource(R.drawable.ic_tomato_48dp); break;
}
return rowView;
}
}
Nun ... ist die Datenbank immer korrekt aktualisiert, aber: manchmal plantsList und quantityLists Repliken einfügen, so Pflanzen zweimal erscheinen oder dreimal und ich will es nicht.
EDIT: Ich gelang es, diese beiden Probleme zu lösen. Jetzt gibt es nur das folgende Problem. Sehr oft tritt dieser Fehler auf:
10-19 19: 28: 19.148 bis 19.148 52,460/.veggarden E/Android Runtime: fatal EXCEPTION: main Prozess: .veggarden, PID: 19148 java.lang.NullPointerException :. Attempt virtuelle Methode 'java.lang.Object android.content.Context.getSystemService (java.lang.String)' auf null Objektreferenz bei .veggarden.MyVegGardenAdapter (MyVegGardenAdapter.java:31) aufzurufen um .veggarden.MyVegGardenFragment $ 1.onDataChange (MyVegGardenFragment.java:85) bei com.google.android.gms.internal.zzbmz.zza (Unbekannte Quelle) bei com.google.android.gms.internal.zzbnz.zzYj (unbekannte Quelle) bei com.google.android.gms.internal.zzboc $ 1.run (Unbekannte Quelle) bei android.os.Handler.handleCallback (Handler.java:751) bei android.os.Handler.dispatchMessage (Handler.java:95) bei android.os.Looper.loop (Looper.java:154) bei android.app.ActivityThread.main (ActivityThread.java:6077) bei java.lang.reflect.Method.invoke (native Methode) bei 01.235.com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:866) bei com.android.internal.os.ZygoteInit.main (ZygoteInit.java: 756)
Bis jetzt dieser Fehler auftritt:
- das erste Mal ich versuche, eine Anlage hinzufügen, wenn ich meine Anlage von db gelöscht (im Kontext nicht null ist, aber nach einer Zugabe Pflanze es ist)
- , wenn ich zu einem anderen Fragment durch eine untere Symbolleiste gehen und dann an dieses Fragment ich wieder eine Pflanze
- beim hinzufügen von vielen Pflanzen (selten und nicht so sicher)
Hier mein up-to-date-Code:
public class MyVegGardenFragment extends Fragment {
private View v;
private ListView listView;
private DatabaseReference database;
private FirebaseAuth auth;
private FirebaseUser us;
private Map<String, Integer> myVegGarden;
private ArrayList<String> plantsList = new ArrayList<>();
private ArrayList<Integer> quantityList = new ArrayList<>();
private MyVegGardenAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myVegGarden = new HashMap<>();
database = FirebaseDatabase.getInstance().getReference();
auth = FirebaseAuth.getInstance();
us = auth.getCurrentUser();
v = inflater.inflate(R.layout.myveggarden_fragment_layout, container, false);
listView = (ListView) v.findViewById(R.id.myVegGarden_list_view);
database.addValueEventListener(new ValueEventListener() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
plantsList = new ArrayList<String>();
quantityList = new ArrayList<Integer>();
User u = dataSnapshot.child("users").child(us.getUid()).getValue(User.class);
if (u != null) {
myVegGarden = u.getMyVegGarden();
if (myVegGarden != null) {
for(Map.Entry<String, Integer> entry : myVegGarden.entrySet()) {
plantsList.add(entry.getKey());
quantityList.add(entry.getValue());
}
}
**line 85**
adapter = new MyVegGardenAdapter(getActivity(), plantsList, quantityList);
listView.setAdapter(adapter);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
FloatingActionButton fab = (FloatingActionButton) v.findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder;
// [...] leaving code for AlertDialog working correctly
builder.setPositiveButton("PLANT", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final String plant = options[plant_picker.getValue()];
final int quantity = quantity_picker.getValue();
if(!adapter.getPlantsList().contains(plant)){
adapter.add(plant, quantity);
}
else {
adapter.updateIfPresent(plant, quantity);
}
if (myVegGarden != null) {
myVegGarden.put(plant, quantity);
database.child("users").child(us.getUid()).child("myVegGarden").setValue(myVegGarden);
}
else {
myVegGarden = new HashMap<String, Integer>();
myVegGarden.put(plant, quantity);
database.child("users").child(us.getUid()).child("myVegGarden").setValue(myVegGarden);
}
dialog.dismiss();
}
});
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
} });
AlertDialog dialog = builder.create();
dialog.show();
}
});
return v;
}
Der Adapter ist das gleiche wie zuvor.
Ich hoffe, dass mir jemand helfen kann.
Ich löste meine Probleme auch dank dir. Jetzt gibt es nur noch ein Problem, bitte schauen Sie, wenn Sie können, ich werde es zu schätzen wissen. – Benny