ArrayList, SimpleCursorAdapter - leci wyjątek

0

Witajcie,
W dalszym ciągu próbuję wrzucić dane pobrane z bazy SQLite z cursora do listy a następnie wyświetlić to w widoku listy w swojej aktywności. Jestem już na coraz lepszej drodze, zrobiłem coś konkretniejszego niż miałem do tej pory. Wygląda to tak, w klasie DatabaseHelper tworzę sobie listę w następujący sposób:

 public ArrayList<HashMap<String, String>> getAllPlayers() {
        try {
            ArrayList<HashMap<String, String>> arraylist = new ArrayList<HashMap<String, String>>();
            HashMap<String, String> map;
            SQLiteDatabase db = this.getReadableDatabase();
            String sqlSelect = "SELECT " + _id + ", " +
                    columnPlayerName  + " FROM " + TABLE_NAME;
            Cursor select = db.rawQuery(sqlSelect, null);
            if(select != null) {
                if(select.moveToFirst()) {
                    do {
                        map = new HashMap<String, String>();
                        map.put("id", select.getString(0));
                        map.put("name", select.getString(1));
                        arraylist.add(map);
                    }
                    while(select.moveToNext());
                }
            }
            select.close();
            db.close();
            return arraylist;
        }
        catch (Exception E) {
            return null;
        }
    }

Teraz w klasie z aktywnością tworzę sobie SimpleCursorAdapter:

public class ManagePlayers extends AppCompatActivity {
    DatabaseHelperPlayer playerDb = new DatabaseHelperPlayer(this);
    ListView playersList;
    ArrayList<HashMap<String, String>> playerList = playerDb.getAllPlayers();


   

   
    private void playersListView() {
        playersList = (ListView) findViewById(R.id.listPlayer);
        SimpleAdapter adt = new SimpleAdapter(this, playerList, R.layout.row_players, new String[]{"id", "name"}, new int[]{R.id.id, R.id.playerNameListView});
        playersList.setAdapter(adt);

    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage_players);

        playersListView();

    }
}

Jeszcze na wszelki wypadek wrzucam jak wygląda mój plik xml z widokiem listy (row_players.xml):

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:stretchColumns="*">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
        <TextView
            android:id="@+id/id"
            android:layout_column="0"
            android:padding="0dp"
            android:layout_span="2"
            />

        <TextView
            android:id="@+id/playerNameListView"
            android:layout_column="1"
            android:padding="0dp"
            />
    </TableRow>
</TableLayout>

i plik z layoutem:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_manage_players"
    tools:context="com.example.user.apk.ManagePlayers">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listPlayer"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:choiceMode="singleChoice" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Player"
        android:id="@+id/addPlayer"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>

Wydawało by się że wszystko jest jak należy a mimo to podczas próby wejścia do aktywności leci mi wyjątek i już nie wiem co jest nie tak. Drugi dzień nad tym siedzę i nie mogę znaleźć błędu. Bardzo Was proszę o pomoc.

Kod błędu:

 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime: FATAL EXCEPTION: main
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime: Process: com.example.ukasz.carrom, PID: 2303
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ukasz.carrom/com.example.ukasz.carrom.ManagePlayers}: java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.-wrap11(ActivityThread.java)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:  Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:100)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.widget.ListView.setAdapter(ListView.java:491)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at com.example.ukasz.carrom.ManagePlayers.playersListView(ManagePlayers.java:62)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at com.example.ukasz.carrom.ManagePlayers.onCreate(ManagePlayers.java:75)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:6237)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.-wrap11(ActivityThread.java) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
01-06 00:00:44.078 2303-2303/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
0

method 'int java.util.List.size()' on a null object reference

0

To jaki jest błąd to ja widzę bo umiem czytać. Tylko nie mogę dojść co go powoduje i w którym miejscu robię źle.

0

Wyłapujesz wszystkie błędy i nie wyrzucasz ich nawet w logach, więc skąd masz wiedzieć gdzie znajduje się błąd?

catch (Exception E) {
return null;
}

A wchodzi w blok catch jeśli zwraca Ci null. Nie wiesz nawet jaki exception wyłapało.

0

Zrób sobie takie coś:

try {
  // cokolwiek
} catch (Exception e) {
   Log.e("ERR", "*** Treść błędu: " + e.getMessage());
}
 

Wtedy w logach w android studio będziesz miał na czerwono pod tagiem "ERR" wypisaną treść błędu. Łatwiej znajdziesz rozwiązanie.
Zrób kilka takich bloków z różnym tagiem albo wiadomością i wtedy znajdziesz w którym miejscu masz błąd.

0

Faktycznie, przez to że łapałem błąd mi go nie wywalało a wyrzuca mi właśnie w tym miejscu. Tak wygląda błąd:
Treść błędu: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference

0

Problem sobie rozwiązałem tylko nie bardzo rozumiem czemu musi to być tak zrobione. A więc do tej pory te dwie deklaracje:

DatabaseHelperPlayer playerDb = new DatabaseHelperPlayer(this);
ArrayList<HashMap<String, String>> playerList = playerDb.getAllPlayers();

miałem bezpośrednio w klasie, następnie miałem utworzoną metodę:

private void playersListView() {
        playersList = (ListView) findViewById(R.id.listPlayer);
        SimpleAdapter adt = new SimpleAdapter(this, playerList, R.layout.row_players, new String[]{"id", "name"}, new int[]{R.id.id, R.id.playerNameListView});
        playersList.setAdapter(adt);
 
    }

i ją sobie wywoływałem:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage_players);
 
        playersListView();
 
    }

I okazało się że to jest źle. Chciałem właśnie jak najwięcej rzeczy robić właśnie w metodach i później je wywoływać. Aby to zadziałało powinno być zrobione tak:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage_players);
        DatabaseHelperPlayer playerDb = new DatabaseHelperPlayer(this);
        ArrayList<HashMap<String, String>> playerList = playerDb.getAllPlayers();
        playersList = (ListView) findViewById(R.id.listPlayer);
        SimpleAdapter adt = new SimpleAdapter(this, playerList, R.layout.row_players, new String[]{"id", "name"}, new int[]{R.id.id, R.id.playerNameListView});
        playersList.setAdapter(adt);

    }

Czy mogę Was prosić o wyjaśnienie czemu tak jak zrobiłem to ja nie zadziałało? I jak powinienem to zrobić prawidłowo tzn żeby było zgodne z normami programowania a jednocześnie działało.

0

a sprawdziłeś co masz przekazywane w playerList jeżeli bylo zainicjowane jako pole klasy? chciałem zrobić DI nie wiedząc co to jest i jak to zrobić :P podejście słuszne tylko narzędzi brak

Dodatkowo nie rób takich kwiatków że masz playerList i playersList gdzie jedno jest jakąś tam tablicą a drugie listView. Nazywaj zmienne tak żeby od razu było wiadomo o co chodzi.

Następna rzecz to ArrayList HashMap. Jeżeli masz coś takiego to znaczy że nie przemyślałeś zupełnie jak to powinno wyglądać.

0

Czyli używając ArrayList HashMap robię błąd? Powiem tak, szukałem rozwiązania problemu który miałem. Musiałem Przekazać kursor do listy tak aby móc go później wyświetlić w innej klasie w widoku ListView w dwóch kolumnach. Szukałem, grzebałem, znalazłem takie rozwiązanie, zaadaptowałem je do swojego projektu i działa prawidłowo. Spełnia moje oczekiwania ale jesli powinienem to zrobić inaczej to chętnie się dowiem co radzisz :). Cały czas się uczę :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1