Autore Topic: findViewById lancia una NullPointerException. Perchè?  (Letto 512 volte)

Offline fanny983

  • Nuovo arrivato
  • *
  • Post: 5
  • Respect: 0
    • Mostra profilo
findViewById lancia una NullPointerException. Perchè?
« il: 10 Ottobre 2013, 16:06:59 CEST »
0
Ciao a tutti,
sono nuova della programmazione Android e sto sviluppando una piccola app giusto per imparare. Ora ho un problema e credo di essermi persa qualche pezzo perchè non capisco da cosa possa dipendere.

Ho la mia classe java MainActivity che estende Activity banalmente fatta in questo modo:

Codice (Java): [Seleziona]
protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

               

        setContentView(R.layout.activity_main);

        Spinner prova = (Spinner)findViewById(R.id.seller);

               

        new ClasseTest();

}


e poi ho la mia ClasseTest così fatta:

Codice (Java): [Seleziona]
public class ClasseTest {

       

        public ClasseTest() {

                Spinner prova = (Spinner)findViewById(R.id.seller);

        }

}


Ora, il primo findViewById contenuto in MainActivity restituisce risultato, mentre il secondo, contenuto nel costruttore della ClasseTest lancia la seguente eccezione:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.app.prova/com.android.app.prova.MainActivity}: java.lang.NullPointerException

e qualche riga sotto leggo

10-10 15:51:21.705: E/AndroidRuntime(10577): Caused by: java.lang.NullPointerException
10-10 15:51:21.705: E/AndroidRuntime(10577): at android.app.Activity.findViewById(Activity.java:18 82)

mi sono persa qualcosa?

Offline kalacta269

  • Utente normale
  • ***
  • Post: 152
  • Respect: +14
    • Mostra profilo
  • Dispositivo Android:
    Asus Transformer pad tf300
  • Sistema operativo:
    windows7
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #1 il: 10 Ottobre 2013, 16:18:23 CEST »
0
Ciao,
L'errore è semplice la differenza fra le due classi è che nella prima classe estendi activity e prendi il riferimento al file xml del tuo layout quando fai l'istruzione
Codice (Java): [Seleziona]
setContentView(R.layout.activity_main); a questo punto puoi istanziare lo spinner cercando l'id nella classe R mentre nella seconda classe non hai riferimento a nessun file xml anche perchè non è un activity e quindi non sa dove andarsi a prendere l'id dello spinner di conseguenza di da null pointer, non capisco poi perché fai
Codice (Java): [Seleziona]
new ClasseTest() qual'è il tuo obbiettivo? 

Offline fanny983

  • Nuovo arrivato
  • *
  • Post: 5
  • Respect: 0
    • Mostra profilo
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #2 il: 10 Ottobre 2013, 16:26:02 CEST »
0
Citazione
non capisco poi perché fai new ClasseTest()

In realtà la classe è più complessa e qui ho riportato solo alcuni pezzi. L'obiettivo comunque è solo quello di istanziare un'altra classe.

Ma come dovrei procedere? Tra le tante prove che ho fatto ho anche esteso la seconda classe con Activity ma il risultato non è cambiato. E' come se in quel punto non avessi più un contesto di riferimento. Sbaglio?

Offline kalacta269

  • Utente normale
  • ***
  • Post: 152
  • Respect: +14
    • Mostra profilo
  • Dispositivo Android:
    Asus Transformer pad tf300
  • Sistema operativo:
    windows7
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #3 il: 10 Ottobre 2013, 16:41:08 CEST »
0
ma tu questo spinner dove lo vuoi utilizzare? in quale classe?

allora per poter utilizzare i componenti presenti nei layout la procedura è la seguente...

Crei il file xml del layout
crei una classe che estende activity
effettui l'overraide del metodo della classe activity setContentView con il layout di riferimento
e dopo di che puoi istanziare il tuoi elementi come spinner bottoni ecc ecc...
quindi se anche nella seconda classe di test estendi activity ma non richiami il setContentView l'app non sa dove andarsi a prende lo spinner e ti da nullPointer quindi per ovviare dovresti richiamare il setContentView.
Anche se cosi hai due activity che hanno lo stesso layout non so se è questo il risultato che vuoi ottenere......

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #4 il: 10 Ottobre 2013, 16:44:26 CEST »
0
Ma la classe ClasseTest è una classe interna vero ?  o_O
Comunque, potresti provare a passare alla tua classe il riferimento dello Spinner :
Codice (Java): [Seleziona]
public class ClasseTest {

        private Spinner mSpinner ;

        public ClasseTest(Spinner s) {
                 mSpinner = s ;
        }

}

Non sapendo però qual'è il tuo obbiettivo e poichè il codice che hai postato è molto poco e poco chiaro...non credo che ti si possa aiutare più di tanto.
Ricardati che il logcat ti da già un ottimo punto di partenza per risolvere la maggior parte dei problemi  ;-)
Se ti da un NullPointerException, fidati, dice la verità !

Offline fanny983

  • Nuovo arrivato
  • *
  • Post: 5
  • Respect: 0
    • Mostra profilo
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #5 il: 10 Ottobre 2013, 17:19:30 CEST »
0
Avete ragione ragazzi. Sostanzialmente le mie sono solo prove quindi probabilmente (anzi sicuramente) sto sbagliando tutto :D

Vi riporto il codice completo (elimino giusto qualcosa, come la creazione del db)

Codice (Java): [Seleziona]
public class MainActivity extends Activity {

        private DbManagement db;
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
               
                .....
                //qui creo il db
                .....

                setContentView(R.layout.activity_main);
       
                new ArticleManag(db);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
        }

}

Codice (Java): [Seleziona]
public class ArticleManag extends Activity {
       
       
        public ArticleManag(DbManagement db) {
                populateSellerSpinner(db);
        }

        private void populateSellerSpinner(DbManagement db) {
                Seller s = new Seller();
                List<String> sellers = s.getAllSellers(db);
               
                Spinner spinner = (Spinner) findViewById(R.id.seller);
               
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, sellers);
               
                adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
               
                spinner.setAdapter(adapter);
               
               
        }

}

Codice (Java): [Seleziona]
public class Seller {
 public List<String> getAllSellers(DbManagement db1){
        List<String> labels = new ArrayList<String>();
       
        SQLiteDatabase db = db1.getReadableDatabase();
        try {
                        // Select All Query
                String selectQuery = "SELECT * FROM Seller";
     
                Cursor cursor = db.rawQuery(selectQuery, null);
     
                // looping through all rows and adding to list
                if (cursor.moveToFirst()) {
                    do {
                        labels.add(cursor.getString(1));
                    } while (cursor.moveToNext());
                }
         
                // closing connection
                cursor.close();
                db.close();
        } catch (Exception e) {
                        e.printStackTrace();
                }      
       
        return labels;
}              
}

Spero si capisca un pò di più.

Post unito: 10 Ottobre 2013, 17:23:06 CEST
Il problema si presenta nel metodo populateSellerSpinner all'istruzione Spinner spinner = (Spinner) findViewById(R.id.seller);

Post unito: 10 Ottobre 2013, 17:59:37 CEST
ho risolto in questo modo:
Codice (Java): [Seleziona]
public class MainActivity extends Activity {

        private DbManagement db;
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
               
                .....
                //qui creo il db
                .....

                setContentView(R.layout.activity_main);
       
                new ArticleManag(db, this);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
        }

}

Codice (Java): [Seleziona]
public class ArticleManag  {
       
        public Activity activity;
       
        public ArticleManag(DbManagement db, Activity _activity) {
                this.activity = _activity;
                populateSellerSpinner(db);
        }

        private void populateSellerSpinner(DbManagement db) {
                Seller s = new Seller();
                List<String> sellers = s.getAllSellers(db);
               
                Spinner spinner = (Spinner)this.activity.findViewById(R.id.seller);
               
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity,
                android.R.layout.simple_spinner_item, sellers);
               
                adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice);
               
                spinner.setAdapter(adapter);
               
               
        }

}

Che ne pensate?
In varie guide ho incontrato il concetto di Inflate, ma non ho ben capito il concetto. Potete spiegarmi cosa sono?  :-[
« Ultima modifica: 10 Ottobre 2013, 17:59:38 CEST da fanny983, Reason: Merged DoublePost »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #6 il: 10 Ottobre 2013, 18:05:03 CEST »
0
Se ho capito bene il codice, secondo me c'è un questione di base che secondo me ti sta creando quasi tutti i problemi e può essere sintetizzata in questa istruzione: new ArticleManag(db). Non prenderlo come una critica, è solo per spiegare in dettaglio.

Semplifico molto: le activity (le classi derivate da Activity) sono classi particolari, sono sinonimo di schermata e possono molto grezzamente essere considerate il "main" del codice.  Ogni schermata (activity) fa gruppo a sé e non ci sono mai due schermate (activity) attive contemporaneamente. Quando da una schermata (activity) ne chiami un'altra, passi totalmente il controllo alla chiamata e la precedente non è più accesibile.

Quindi "new ArticleManag(db)" sostanzialmente non serve a niente. Se intendi chiamare una seconda schermata (activity) non è quello il modo, si usano gli Intent, e anche usando gli Intent non c'è nessuna OnCreate() che si occupi di creare la parte grafica della schermata).
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline fanny983

  • Nuovo arrivato
  • *
  • Post: 5
  • Respect: 0
    • Mostra profilo
Re:findViewById lancia una NullPointerException. Perchè?
« Risposta #7 il: 10 Ottobre 2013, 18:36:38 CEST »
0
Ok, messaggio ricevuto! Spero di impratichirmi con il tempo. Grazie mille  ;-)