Asyncroner Task & BaseAdapter

  • 12 Antworten
  • Letztes Antwortdatum
joshua1996

joshua1996

Stamm-User
111
Hallo,

ich habe in meiner App einen async Task, der mir ein JSON-Array von einer URL holt. Im ersten Anlauf habe ich einfach den String in eine ListView eingelesen.
Das hat so weit auch gut funktioniert, sieht halt nur sehr bescheiden aus...

Also dachte ich mir suche ich mir mal ein Tutorial, programmiere das nach, setzte mich damit auseinander und schreibe es so um, dass es (theoretisch) in meine App passt.
In der Test-App ging der Baseadapter auch Problemlos.

Nun hab ich den in meine richtige App eingebaut, und bekomme jetzt einen ForceClose.
Als Error bekomme ich "The constructor StartAdapter(MainActivity.Posts, String[], String[], String[], String[]) is undefined"
Dann hab ich die ganzen Änderungsvorschläge von Eclipse druchgeführt. Jetzt kann ich die App immerhin auf meinem Handy starten, bis ich den Asyncronen Task ausführe.

Hier der LogCat dazu:
Code:
04-25 14:22:26.690: W/dalvikvm(29186): threadid=1: thread exiting with uncaught exception (group=0x41ec1d40)
04-25 14:22:26.691: E/AndroidRuntime(29186): FATAL EXCEPTION: main
04-25 14:22:26.691: E/AndroidRuntime(29186): Process: de.swg, PID: 29186
04-25 14:22:26.691: E/AndroidRuntime(29186): java.lang.NullPointerException
04-25 14:22:26.691: E/AndroidRuntime(29186): at de.swg.MainActivity$proPosts.onPostExecute(MainActivity.java:612)
04-25 14:22:26.691: E/AndroidRuntime(29186): at de.swg.MainActivity$proPosts.onPostExecute(MainActivity.java:1)
04-25 14:22:26.691: E/AndroidRuntime(29186): at android.os.AsyncTask.finish(AsyncTask.java:632)
04-25 14:22:26.691: E/AndroidRuntime(29186): at android.os.AsyncTask.access$600(AsyncTask.java:177)
04-25 14:22:26.691: E/AndroidRuntime(29186): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
04-25 14:22:26.691: E/AndroidRuntime(29186): at android.os.Handler.dispatchMessage(Handler.java:102)
04-25 14:22:26.691: E/AndroidRuntime(29186): at android.os.Looper.loop(Looper.java:136)
04-25 14:22:26.691: E/AndroidRuntime(29186): at android.app.ActivityThread.main(ActivityThread.java:5102)
04-25 14:22:26.691: E/AndroidRuntime(29186): at java.lang.reflect.Method.invokeNative(Native Method)
04-25 14:22:26.691: E/AndroidRuntime(29186): at java.lang.reflect.Method.invoke(Method.java:515)
04-25 14:22:26.691: E/AndroidRuntime(29186): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
04-25 14:22:26.691: E/AndroidRuntime(29186): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
04-25 14:22:26.691: E/AndroidRuntime(29186): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:133)
04-25 14:22:26.691: E/AndroidRuntime(29186): at dalvik.system.NativeStart.main(Native Method)
04-25 14:22:26.694: W/ActivityManager(1021):   Force finishing activity de.swg/.MainActivity

Hier der Adapter:
Code:
package de.swg;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

class StartAdapter extends BaseAdapter {

Context context;
    String[] name1;
    String[] name2;
    String[] text;
    String[] date;
    private static LayoutInflater inflater = null;

    public StartAdapter(Context context, String[] name1, String[] name2, String[] text, String[] date) {
        // TODO Auto-generated constructor stub
        this.context = context;
        this.name1 = name1;
        this.name2 = name2;
        this.text = text;
        this.date = date;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return name1.length;
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return name1[position];
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        View vi = convertView;
        if (vi == null)
            vi = inflater.inflate(R.layout.row, null);
        TextView text1 = (TextView) vi.findViewById(R.id.textView1);
        text1.setText(name1[position]);
        TextView text2 = (TextView) vi.findViewById(R.id.textView2);
        text2.setText(name2[position]);
        TextView text3 = (TextView) vi.findViewById(R.id.textView3);
        text3.setText(text[position]);
        TextView text4 = (TextView) vi.findViewById(R.id.textView4);
        text4.setText(date[position]);
        return vi;
    }
}

Und hier der AsyncTask:
Code:
class Posts extends AsyncTask {
        @Override
        protected void onPreExecute() {
            // set the progress bar view
            refreshMenuItem.setActionView(R.layout.action_progressbar);
 
            refreshMenuItem.expandActionView();
        }
 
        @Override
        protected String doInBackground(String... params) {
        
        JSONParser jParser = new JSONParser();
        JSONObject json = jParser.getJSONFromUrl(urlStart);
        try {
        start = json.getJSONArray(TAG_START);
        Start_PosterName_List.clear();
        Start_EmpfangerName_List.clear();
        Start_Corkboard_List.clear();
        Start_DateTime_List.clear();
        for (int i = 0; i < start.length(); i++) {
                JSONObject c = start.getJSONObject(i);
                corkboard_id = c.getString(TAG_CORKBOARD_ID);
                corkboard_text = c.getString(TAG_CORKBOARD_TEXT);
                datetime = c.getString(TAG_DATETIME);
                poster_id = c.getString(TAG_POSTER_ID);
                poster_name = c.getString(TAG_POSTER_NAME);
                poster_surname = c.getString(TAG_POSTER_SURNAME);
                empfanger_id = c.getString(TAG_EMPFANGER_ID);
                empfanger_name = c.getString(TAG_EMPFANGER_NAME);
                empfanger_surname = c.getString(TAG_EMPFANGER_SURNAME);
                sort = c.getString(TAG_SORT);
                
                Start_PosterName_List.add(poster_name + " " + poster_surname);
                Start_EmpfangerName_List.add(empfanger_name + " " + empfanger_surname);
                Start_Corkboard_List.add(corkboard_text);
                Start_DateTime_List.add(datetime);
        }
        }
        
        catch (JSONException e) {
        e.printStackTrace();
        }
        return null;
        }
 
        @Override
        protected void onPostExecute(String result) {
        
        String[] name1 = (Start_PosterName_List.toArray(new String[0]));
            String[] name2 = (Start_EmpfangerName_List.toArray(new String[0]));
            String[] text = (Start_Corkboard_List.toArray(new String[0]));
            String[] date = (Start_DateTime_List.toArray(new String[0]));
            
            lvHome.setAdapter(new StartAdapter(this, name1, name2, text, date));
            
            refreshMenuItem.collapseActionView();
            // remove the progress bar view
            refreshMenuItem.setActionView(null);
        }
    };

Ich denke das Problem liegt darin, das der AsyncTask MainActivity.Posts zurück gibt, der BaseAdapter damit aber nix "anfangen" kann, da er sowas wie eine Activty erwartet.
Ich weiß jetzt aber nicht wie ich dem sage, dass er einen AsyncTask akzeptieren soll...

Ich hoffe mir kann wer zeigen wo ich sch**** gebaut habe, und bedanke mich schon mal für alle Antworten ;)


EDIT: das Problem lag beim instanziieren der ListView, welche ich im onCreate stehen hatte.
Nun habe ich die ListView im AsyncTask instanziiert und nun geht es problemlos

Danke @markus.tullius
 
Zuletzt bearbeitet:
Da du mit StartAdapter ja nur den BaseAdapter erweiterst, wie kannst du da einen Constructor mit dem Namen StartAdapter haben? Stell mir nur gerade die Frage, weil es ja auch der Error sagt o.o

Ansonsten, dein Logcat sagt, dass onPostExecute einen null Wert übergeben bekommt. Klar, denn doInBackground hat ja als return nur null. MainActivity.java Zeile 612 sollte das Problem liegen, die Ursache kannste ja sicherlich schnell finden :)

So viel Zeit hab ich nun leider nicht um alles genau anzuschauen, zumal nicht alles dabei ist.
 
  • Danke
Reaktionen: joshua1996
new StartAdapter(this, name1, name2, text, date)

Das kann eigentlich schon nicht funktionieren.
StartAdapter braucht einen Context als erstes Parameter. Du übergibst aber den AsyncTask der kein Context ist.

Ich würde auch den Rückgabewert von doInBackground auf Void ändern, wenn du da eh nichts zurück gibst
 
  • Danke
Reaktionen: joshua1996
Zeile 612 ist "lvHome.setAdapter(new StartAdapter(this, name1, name2, text, date));

Und das mit dem BaseAdapter hat ja vorher in meiner Beispiel-App ja genauso funktioniert...
Dashalb vermute ich mal, dass der AsyncTask das Problem ist

Aber schonmal danke ;)

@amfa: Und mein Problem liegt ja genau da :D
was soll ich dem für einen Context übergeben?

Und danke für den Hinweis mit dem void :razz:
 
Naja den aktuellen ApplicationContext halt ;)

Wenn ich das richtig sehe nutzt die die params in der doInBackground Methode ja sowieso nicht, im zweifel übergibst du da halt den Context als Parameter und könntest ihn dann direkt sogar als result zurück geben und dann in der onPostExecute nutzen.

Ist ein wenig gehackt denk ich aber sollte funktionieren.
 
  • Danke
Reaktionen: joshua1996
Was wäre denn der aktuelle ApplicationContext?
Ich hab es schon mit getApplicationContext(), getBaseContext(), this und mit MainActivity.Posts ...
Und alles funktioniert nicht.
Stehe grad auf dem Schlauch :(
 
Laut stacktrace ist das ja sogar eine innere Klasse.
Da müsste eigentlich
MainActivity.this
funktionieren.
 
  • Danke
Reaktionen: joshua1996
MainActivity.this habe ich auch schon einmal anfangs probiert...
Bekomme die selbe NullPointerExecption in Line 612
Also beim Aufruf vom Adapter.
Wie kann ich denn den Context umgehen oder kann ich das anders lösen?
 
Hast du das field lvHome instanziiert?
Ein null-Objekt wirft ein Exception, wenn es eine Methode ausführen soll.

NullPointerException (Java Platform SE 7 )

Wenn im Konstruktor des Adapter ein Fehler geworfen würde, müsste er im Logtrace eigentlich auftauchen.
 
  • Danke
Reaktionen: joshua1996
Ich habe im onCreate() den ListView instanziiert und einer ID zugewiesen.
Nun hab ich die ID testweise im Asynchronen Task zugewiesen, und es hat funktioniert :)

Vielen Dank für die Lösung ;) :thumbsup:
 
hmm bleibt die Frage wo genau du die ListView instanziiert hast.
Eigentlich müsste das in der OnCreate Methode funktionieren.
Es sei denn du machst es vor der setContentView() methode oder so.
 
Den ListView habe ich nach dem setContentView instanziiert.
Nur kommen meine mittlerweile 700 Zeilen Code nicht von irgendwo ;)
Ich habe mit einem Navigation-Drawer gearbeitet, welcher mit Fragmenten arbeitet...
Und ich habe die ID gesucht, bevor ich das neue Fragment aufgerufen habe.
Er hat also versucht die ListView einzutragen, ohne das sie aktuell verwendet wird...

So denke ich mal in der Theorie :D
Aber das wichtigste ist das die App mit dem BaseAdapter funktioniert und ich dann bis Montag die App zu 100% fertig habe ;)

Nochmals danke für alle antworten :D
 
Bei 700 Zeilen Code in einer Klasse, solltest du anfangen, Teile davon auszulagern. Schon der Übersicht halber.
 
  • Danke
Reaktionen: joshua1996
Zurück
Oben Unten