Android Studio: Auf Datenbank mit zwei Spinner zugreifen.

P

prof.dopenudel

Neues Mitglied
2
Hi Leute,

bin gerade an einer App dran. Verzweifle aber maßlos. Irgendwie geht mir das programmieren so langsam auf den Zeiger :D

Naja. Also. Möchte gerne ein App programmieren, in der die User ein erstes Wort eingeben können und ein zweites Wort auch. Das alles wird in der Firebase Database gespeichert. Danach soll man über zwei Spinner jeweils auf die Datenbank zugreifen können (also Spinner1 auf die ersten Wörter und Spinner2 auf die zweiten Wörter)
Habe soweit alles eingerichtet. Nur habe ich massenweise Probleme wenn es darum geht, ein zweites Wort einzufügen, geschweige denn auf den Spinner1 zuzugreifen.

Habe den Internetzugriff in der Manifest.xml hinzugefügt und die Firebase Sachen implementiert.

Hier mal meine Codes.

MainActivity:

Code:
public class MainActivity extends AppCompatActivity {

    DatabaseReference db, db2;
    FirebaseHelper helper;
    //FirebaseHelper2 helper2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Spinner sp= (Spinner) findViewById(R.id.sp);

        //SETUP FB
        db=FirebaseDatabase.getInstance().getReference();
        helper=new FirebaseHelper(db);

        sp.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,helper.retrieve()));

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                displayInputDialog();
            }
        });

        /*
       Spinner sp2= (Spinner) findViewById(R.id.sp2);

        //SETUP FB
        db=FirebaseDatabase.getInstance().getReference();
        helper2=new FirebaseHelper2(db);

        sp2.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,helper.retrieve()));

        Button fab1 = (Button) findViewById(R.id.fab2);
        fab1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                displayInputDialog2();
            }
        });
*/
    }

    //DISPLAY INPUT DILAOG
    private void displayInputDialog()
    {
        Dialog d=new Dialog(this);
        d.setTitle("Firebase database");
        d.setContentView(R.layout.input_dialog);

        final EditText nameTxt= (EditText) d.findViewById(R.id.nameEditText);
        Button saveBtn= (Button) d.findViewById(R.id.saveBtn);

        //SAVE
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //GET DATA
                String name=nameTxt.getText().toString();

                //set data
                Spacecraft s=new Spacecraft();
                s.setName(name);

                //SAVE
                if(name != null && name.length()>0)
                {
                    if(helper.save(s))
                    {
                        nameTxt.setText("");
                    }

                }else
                {
                    Toast.makeText(MainActivity.this, "Name Cannot Be Empty", Toast.LENGTH_SHORT).show();
                }

            }
        });

        d.show();
    }

/*
    //DISPLAY INPUT DILAOG
    private void displayInputDialog2()
    {
        Dialog d2=new Dialog(this);
        d2.setTitle("Firebase database");
        d2.setContentView(R.layout.input_dialog2);

        final EditText nameTxt2= (EditText) d2.findViewById(R.id.nameEditText2);
        Button saveBtn2= (Button) d2.findViewById(R.id.saveBtn2);

        //SAVE
        saveBtn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //GET DATA
                String name2=nameTxt2.getText().toString();

                //set data
                Spacecraft2 s2=new Spacecraft2();
                s2.setName(name2);

                //SAVE
                if(name2 != null && name2.length()>0)
                {
                    if(helper2.save(s2))
                    {
                        nameTxt2.setText("");
                    }

                }else
                {
                    Toast.makeText(MainActivity.this, "Name Cannot Be Empty", Toast.LENGTH_SHORT).show();
                }

            }
        });

        d2.show();
    }
*/
}

FirebaseHelper:

Code:
public class FirebaseHelper {

    DatabaseReference db;
    Boolean saved=null;

    public FirebaseHelper(DatabaseReference db) {
        this.db = db;
    }

    //SAVE
    public  Boolean save(Spacecraft spacecraft)
    {
        if(spacecraft==null)
        {
            saved=false;
        }else
        {
            try
            {
                db.child("Spacecraft").push().setValue(spacecraft);
                saved=true;
            }catch (DatabaseException e)
            {
                e.printStackTrace();
                saved=false;
            }
        }

        return saved;
    }

    //READ
    public ArrayList<String> retrieve()
    {
        final ArrayList<String> spacecrafts=new ArrayList<>();

        db.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                fetchData(dataSnapshot,spacecrafts);
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                fetchData(dataSnapshot,spacecrafts);

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        return spacecrafts;
    }

    private void fetchData(DataSnapshot snapshot,ArrayList<String> spacecrafts)
    {
        spacecrafts.clear();
        for (DataSnapshot ds:snapshot.getChildren())
        {
            String name=ds.getValue(Spacecraft.class).getName();
            spacecrafts.add(name);
        }

    }
}

Spacecraft:

Code:
public class Spacecraft {

    String name;

    public Spacecraft() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


Die Layouts füge ich auch noch hinzu:

Code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_gravity="bottom|end"
        android:layout_marginBottom="32dp"
        android:layout_marginEnd="36dp"
        app:srcCompat="@android:drawable/ic_dialog_email" />

    <Button
        android:id="@+id/fab2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignTop="@+id/fab"
        android:layout_gravity="center_vertical"
        android:layout_marginStart="28dp" />

</RelativeLayout>


Input:

Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="20dp"
        android:orientation="vertical"
        android:paddingLeft="15dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="20dp"
        android:paddingRight="15dp"
        android:paddingTop="50dp">

        <android.support.design.widget.TextInputLayout
            android:id="@+id/nameLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/nameEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:hint= "Name" />
        </android.support.design.widget.TextInputLayout>

        <Button android:id="@+id/saveBtn"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Save"
            android:clickable="true"
            android:background="@color/colorAccent"
            android:layout_marginTop="40dp"
            android:textColor="@android:color/white"/>

    </LinearLayout>

</LinearLayout>

content:

Code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <Spinner
        android:id="@+id/sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="121dp" />

    <Spinner
        android:id="@+id/sp2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="216dp" />

</RelativeLayout>



Sorry für die vielen Codes.

Also. Habe noch eine Spacecraft2.class und eine FirebaseHelper2.class. Dort habe ich eigentlich nur die Variablen geändert - also eine 2 hinten hinzugefügt (wahrscheinlich funktioniert das so nicht? :D)
Habe auch noch ein zweites input_dialog2.xml hinzugefügt.


Wenn ich jetzt also die App starte, dann kann ich über die zwei Buttons beide input Layouts öffnen. Sobald ich aber in das Feld klicke wird die App geschlossen.

Code:
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.user.myapplication, PID: 17222
                  java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
                      at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:445)
                      at android.widget.ArrayAdapter.getView(ArrayAdapter.java:407)
.....

Anfangs hat das funktioniert (habe auch Einträge in der Datenbank) aber irgendwie funktioniert es jetzt nicht mehr.
Es ist doch kein null objekt?

Das Selbe passiert, wenn ich auf die Spinner klicke

Code:
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.user.myapplication, PID: 17505
                  java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
                      at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:445)
                      at android.widget.ArrayAdapter.getDropDownView(ArrayAdapter.java:493)
                      at android.widget.Spinner$DropDownAdapter.getDropDownView(Spinner.java:994)
                      at android.widget.Spinner$DropDownAdapter.getView(Spinner.java:990)
                      at android.widget.Spinner.measureContentWidth(Spinner.java:856)
                      at android.widget.Spinner$DropdownPopup.computeContentWidth(Spinner.java:1225)
                      at android.widget.Spinner$DropdownPopup.show(Spinner.java:1251)
                      at android.widget.Spinner.performClick(Spinner.java:780)
                      at android.support.v7.widget.AppCompatSpinner.performClick(AppCompatSpinner.java:442)
                      at android.view.View$PerformClick.run(View.java:24710)
                      at android.os.Handler.handleCallback(Handler.java:789)
                      at android.os.Handler.dispatchMessage(Handler.java:98)
                      at android.os.Looper.loop(Looper.java:251)
                      at android.app.ActivityThread.main(ActivityThread.java:6589)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)


Es tut mir leid, dass das jetzt so ein langer Text geworden ist. Hoffentlich schreckt euch das nicht ab.

Das wäre echt super, wenn Ihr mir helfen könntet. Bin leider kein Ass im Programmieren...

Danke euch schon einmal im Voraus!

Grüße :biggrin:
 
Hi, ich würde dir gerne helfen. Ich kenne mich auch mit Firebase aus.

Könntest du mir aber dein ganzes Projekt als ZIP oder auf Github/Bitbucket zur Verfügung stellen? (Natürlich ohne die Passwörter etc)
Dann könnte ich es laufen lassen und direkt am Code helfen. So mit den Texten ist mir das zu aufwendig.
 
  • Danke
Reaktionen: prof.dopenudel
Hi also meiner Meinung nach liegt es daran das die App abstürzt.
Du erstellst deine Edittext Variable final somit kann in der onklick Methode ihr kein Wert zugewiesen werden. Ein Edittext Objekt als final ist sinnlos da kannst du nie etwas eingeben.
Lösung erstelle die Variable global im Klassen Rumpf. Setze sie meinetwegen dort wo du sie jetzt erstellst.
Wenn die Variable global ist kannst du auch aus einer callback Methode ohne den final Trick darauf zugreifen.

Bin deinen Code nicht komplett durch gegangen. Kann sein das da noch mehr Fehler sind.

Frage wieso Programmiererst du wenn es dir so auf den Zeiger geht.:rolleyes2:

Ps.
Hier willst du deine unveränderbare final Variable löschen was natürlich nicht geht.
nameTxt.setText("");
nameTxt2.setText("");
Die Variable wird immer lehr sein denn nach dem erzeugen Kann sie nicht verändert werden und zum Zeitpunkt der Erstellung hatte sie noch keinen Wert.



Lg J.
[doublepost=1528387806,1528383248][/doublepost]So ich noch mal.
Auch hier in deiner Helper Klasse machst du den gleichen Fehler.

final ArrayList<String> spacecrafts=new ArrayList<>();

db.addChildEventListener(new ChildEventListener() {
@override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot,spacecrafts);
}



Wieder eine final variable der du später etwas zu weisen willst. Du willst in ihr die werte aus der db speichern. Geht auch nicht da final.
Mit fetch willst du in ihr was speichern was wie gesagt nicht geht.
Deshalb stürzt die App beim klick auf den Spinner ab.

Der vorherige Post ist der Grund warum es beim klick in dem Dialog abstürzt.

LG J.
 
  • Danke
Reaktionen: prof.dopenudel
Kardroid schrieb:
Hi, ich würde dir gerne helfen. Ich kenne mich auch mit Firebase aus.

Könntest du mir aber dein ganzes Projekt als ZIP oder auf Github/Bitbucket zur Verfügung stellen? (Natürlich ohne die Passwörter etc)
Dann könnte ich es laufen lassen und direkt am Code helfen. So mit den Texten ist mir das zu aufwendig.

Danke. Das ist ein super Angebot. Werde dann einmal die Passwörter raus nehmen und es Dir schicken. Danke schon einmal! :)


@jogimuc

Hat leider nichts gebracht. Bringt mir wieder den gleichen Fehler. Aber danke für deine Antwort!
 
Hallo ich sagte ja das da noch mehr fehler drin sein können.
Auf jedenfall ist das mit dem final falsch.

Prüfe im Debugger ob deine "spacecrafts" werte enthält.
In der "fetchData" Methode ist es eine neue Liste, den es wird in java nicht die Reverenz (Pointer) sondern eine Copy übergeben.
(Java macht Call by Value nicht Call by Reverenz)

Innerhalb der Methode FetchData wird der Wert aus der DB deiner Liste( Copy ) hinzugefügt werden, einen Rückgabe Wert hat die Methode nicht. Selbst wenn dann würdest du wieder in die Final Variable schreiben wollen was nicht geht.

Beim lesen der DB fehlt mir auch die Reverenz auf das Objekt.
db=FirebaseDatabase.getInstance().getReference(); keine angabe von wo du lesen willst.
Somit liest du die gesamte DB und nicht nur die Strings für Spinner1 oder 2.

Beim schreiben in die DB
db.child("Spacecraft").push().setValue(spacecraft);
müste das so aussehen
db.child("Spacecraft").push().setValue(spacecraft.getname );
Du willst einen String speichern und nicht die Instanz der Kasse.


Zeige mal wie du den Code jetzt umgestellt hast. Main und Helper Klasse reichen.
 
Zuletzt bearbeitet:
jogimuc schrieb:
Auf jedenfall ist das mit dem final falsch.

Nö, das passt, wieso sollte das falsch sein? Er versucht ja nicht die Referenz des EditText zu ändern, sondern einen Wert innerhalb des EditText, das geht natürlich.

jogimuc schrieb:
In der "fetchData" Methode ist es eine neue Liste, den es wird in java nicht die Reverenz (Pointer) sondern eine Copy übergeben.
(Java macht Call by Value nicht Call by Reverenz)
Nein, ist keine Kopie, ist die originale. Java macht dem Namen nach Call-by-value, es wird aber eine Referenz übergeben. Ich kann den INHALT eines übergebenen Objekts ändern, und die Änderungen sind im caller zu sehen. Ich kann aber NICHT einem Parameter ein neues Objekt zuweisen und erwarten, dass der caller das sieht, der sieht nach wie vor die übergebenen Instanz.

jogimuc schrieb:
Innerhalb der Methode FetchData wird der Wert aus der DB deiner Liste( Copy ) hinzugefügt werden, einen Rückgabe Wert hat die Methode nicht. Selbst wenn dann würdest du wieder in die Final Variable schreiben wollen was nicht geht.
siehe oben


Leider hab ich noch nicht Firebase Datenbanken gearbeitet, deswegen kann ich dir beim Hauptthema nicht helfen.
 
  • Danke
Reaktionen: Kardroid
Danke deek, ich war mir auch sicher, dass man final Variablen ändern kann, nur nicht neu zuweisen kann.

Ich habe die Sourcen vom Threadstarter erhalten, eine Firebase-Datenbank erstellt und eingebunden.
Bei mir stürzt die App nicht ab, ich helfe dem TS über PMs, also nicht wundern, wenn hier nicht mehr viel rein kommt :)
 
  • Danke
Reaktionen: deek
Kein Thema, ich wollte auch hauptsächlich hier nichts falsches stehen haben, auch wenn ich zum eigentlichen Problem wie gesagt nichts beizutragen habe.
 
Hallo möchte nur noch soviel bemerken eine Finale variable sollte nicht zur Laufzeit veränderbar sein. Ist eigentlich eine konzertante.
Probiert es aus.
 
Sorry, aber da muss ich nichts ausprobieren. Du kannst die Referenz nicht ändern den Inhalt schon.
final != immutable
 

Ähnliche Themen

D
Antworten
23
Aufrufe
2.517
Data2006
D
5
Antworten
0
Aufrufe
1.142
586920
5
SaniMatthias
Antworten
19
Aufrufe
943
swa00
swa00
Zurück
Oben Unten