NullPointerException trotz gefüllter ArrayList

  • Antworten:3
Simon2202
  • Forum-Beiträge: 9

07.11.2018, 23:02:18 via Website

Meine App
Es sollte ein simples Spiel werden, bei Appstart lasse ich eine Liste mit Häusern generieren. Diese will ich dann später in einer anderen Activity anzeigen.

Mein Problem
Ich habe versucht herauszufinden an welchem Punkt die Daten verloren gehen, meine Debug Logs (siehe Code unten) zeigen mir jedoch überall, dass die Liste in Ordnung sein sollte.

Mein Code
Houses (hier lasse ich über einen Thread aus der MainActivity meine Häuser generieren und gebe diese dann wieder an die MainActivity zurück)

public class Houses{

ArrayList<Integer> classes = new ArrayList<>();
int[][] NewHouseProps = new int[20][10];
int[][] HouseProps;

public Houses(){
}


public ArrayList<Integer> GenerateHouses(){
    Log.d("Generate Houses","!!");
    for(int id=0; id<=8; id++){
            Random r = new Random();
            int h_class, garage = 0, rooms = 0, furn = 0, balkon = 0, pool = 0;
            h_class = r.nextInt(4); //Klasse
            if(h_class == 0){
                rooms = r.nextInt(4)+1;
                balkon = r.nextInt(1);
            }else if(h_class == 1){
                rooms = r.nextInt(3)+3;
                garage = r.nextInt(1)+1;
                pool = r.nextInt(1);
                balkon = r.nextInt(2);
            }else if(h_class == 2){
                rooms = r.nextInt(3)+2;
                garage = r.nextInt(2)+2;
                pool = r.nextInt(1);
            }else if(h_class == 3){
                rooms = r.nextInt(8)+6;
                garage = r.nextInt(6)+4;
                pool = r.nextInt(1);
                balkon = r.nextInt(3);
            }
            furn = r.nextInt(1);

            int price = GenerateHousePrice(id, h_class, garage, rooms, furn, balkon, pool);
            NewHouseProps[id][0] = h_class;
            NewHouseProps[id][1] = price;
            NewHouseProps[id][2] = rooms;
            NewHouseProps[id][3] = furn;
            NewHouseProps[id][4] = balkon;
            NewHouseProps[id][5] = pool;
            NewHouseProps[id][6] = garage;
            classes.add(h_class);
            Log.d("GenerateHouses","ID: "+id+" CLASS: "+h_class);
            Log.d("GenerateHouses","CLASSES: "+classes.get(id));
            Log.d("GenerateHouses","PROPS: "+NewHouseProps[id][0]);
    }
    for(int id=0;id<=8;id++) {

        Log.d("Generate Houses RETURN", "ID: " + id + " CLASS: " + classes.get(id));
    }
    return classes;

}

public int GenerateHousePrice(int id, int h_class, int garage, int rooms, int furn, int balkon, int pool){

    int price = 0, pricep = 0;
    Random r = new Random();
    if(h_class == 0){
        price = r.nextInt(150000)+50000; // 50 - 200 tausend
        price += rooms * 7500;
    }
    else if(h_class == 1){
        price = r.nextInt(165000)+85000; //85 - 250 tausend
        price += rooms * 12500;
    }
    else if(h_class == 2){
        price = r.nextInt(300000)+100000; //100 - 400 tausnd
        price += rooms * 20000;
    }
    else if(h_class == 3){
        price = r.nextInt(800000)+500000; // 500 - 1.3 Mill.
        price += rooms * 15000;
    }

    if(garage > 0){
        pricep += price*0.20;
        pricep += garage * 500;
    }
    if(furn == 1){
        pricep += price*0.25;
    }
    if(balkon > 0){
        pricep += price*0.1;
        pricep += balkon*500;
    }
    if(pool == 1){
        pricep += 20000;
    }
    price += pricep;
    return price;
}

}

BuyHousesActivity(Hier sollten die Häuser dann in einem ViewPager angezeigt werden, hier bekomme ich dann auch die Exception) - siehe unten markiert.

public class BuyHousesActivity extends FragmentActivity {

ArrayList<Integer> classes = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_buy_houses);
    Bundle bundle = getIntent().getExtras();
    classes = bundle.getIntegerArrayList("classes");

    for(int id=0;id<=8;id++){
        Log.d("BuyHousesActivity","ID: "+id+" CLASS: "+classes.get(id));
    }
    ViewPager viewPager = findViewById(R.id.vpPager);
    viewPager.setAdapter(new MyViewPagerAdapter(getSupportFragmentManager(), classes)); //NullPointerException

}

protected class MyViewPagerAdapter extends FragmentStatePagerAdapter {
    int clicker;
    ArrayList<Integer> pclasses;
    ArrayList<Integer> threeclasses;

    MyViewPagerAdapter(FragmentManager fm, ArrayList<Integer> classes) {
        super(fm);
        pclasses = classes;
        for(int id=0;id<=8;id++){
            Log.d("Adapter ","ID: "+id+" CLASS: "+classes.get(id)+" PCLASS: "+pclasses.get(id));
        } //Hier werden mir die Klassen richtig ausgegeben
        if(clicker == 0){
            for(int id=0;id<=2;id++) {
                threeclasses.add(pclasses.get(id)); //NullPointerException
            }
        }else if(clicker == 1){
            for(int id=3;id<=5;id++) {
                threeclasses.add(pclasses.get(id));
            }
        }else if(clicker == 2){
            for(int id=6;id<=8;id++){
                threeclasses.add(pclasses.get(id));
            }
            clicker = 0;
            return;
        }
        clicker++;
        return;
    }

    @Override
    public int getCount() {
        return pclasses.size()/3;
    }

    @Override
    public Fragment getItem(int position) {
        return FragmentBuyHouse.newInstance(threeclasses);
    }
}

Ich hoffe Ihr könnt mir helfen zu verstehen was ich falsch gemacht habe.

mfG

Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

08.11.2018, 03:39:14 via App

Hallo Simon2202,

im ViewPagerAdapter ist die ArrayList threeclasses zwar definiert, wurde aber nie mit new ...() instanziiert.
Daher bekommst du beim Versuch ein add zu machen die NuPointerException.

Was ich mich allerdings Frage:
Warum machst du es dir mit den ganzen IDs und verweisen so schwer?
Kennst du OOP nicht richtig?
Eine Klasse House und eine Art HouseFactory welche eine List erzeugt, wäre hier deutlich Sinnvoller und du wärst damit komplett Objektorientiert.
So hast du ständig nur Integers und musst am Ende wieder aus deinen Arrays die eigentlichen Daten lesen...

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
swa00
Kommentieren
Simon2202
  • Forum-Beiträge: 9

08.11.2018, 08:06:53 via Website

Danke für deine Antwort ich werde es später probieren.

Bin mir nicht ganz sicher, was du mit deinem zweiten Teil meinst. Meine Klasse "GenerateHouses" gibt mir eh eine Liste zurück, ich brauche die einzelnen Integer Werte weil die im Endeffekt bestimmen was im ViewPager angezeigt wird (3 Häuser pro Fragment).
Aber Ja, da ich gerade erst beginne hat es wohl noch eine hohe Verbesserungsmöglichkeit. Also falls du mir ein paar Stichwörter geben könntest wie du es ändern würdest wäre ich dir sehr dankbar.

mfG

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

08.11.2018, 16:07:00 via Website

Klar, dass du die Werte brauchst, aber so wie du das akutell machst, ist das nicht im Sinn von OOP.
Hier mal ein Tut dazu:
http://www.programmierenlernenhq.de/grundlagen-der-objektorientierten-programmierung-in-java/

Du könntest das so lösen:

class House{
  //varDef
 private  int class;
 private int garage;
 private int rooms;
 private int  furn;
 private int balkon;
 private int  pool;


 // constructor
  public House(int class,int garage,int rooms,int furn,int balkon,int pool){
     this.class = class;
    this.garage = garage;
   this.rooms = rooms;
   this.furn = furn;
   this.balkon = balkon;
   this.pool = pool;
}

//div. getters (evtl setzters) to private vars


}


class HouseFactory{

public static List<House> generateHouses(){
 List<House> houses = new ArrayList<House>();

// calc house properties in loop an init like this:
 House h = new House(class,garage,rooms,furn,balkon,pool);

houses.add(house);

return houses;
}


}

Wenn du diese Konstruktion fertig implementierst, dann kannst du deine Liste aller Häuser mit

List houses = HouseFactory.generateHouses(); //generieren.

Dann kannst du die Liste deiner anderen Activity mitgeben (muss evtl. serializable sein) und dann arbeitest du datatt mit ArrayVerweisen mit deiner Liste:

für ein Haus als abfrage: int house2Rooms = houses.get(1).getRooms(); //etc...

Ich hoffe das hilft dir weiter.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Ludy
Kommentieren