listview nach offline Daten Einspeisung aktualisieren?

  • Antworten:24
  • Bentwortet
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 13:20:22 via App

Hallo Leute,

Von meinem Server werden Daten abgerufen und in eine tut gespeichert.

Danach werden sie via simpleAdapter in einer listactivity eingepflegt.

Quasi via setlistAdapter.

Nun wird mit einem service auf der Datenbank geprüft ob neue Einträge da sind. Wenn ja werden sie an die offline txt angehangen.

Meine Frage : Wie aktualisiere ich die listview im Vordergrund wenn ich weiß das neue Einträge in der offline Datei vorhanden sind?

Antworten
Fabian Simon
  • Forum-Beiträge: 359

08.04.2014, 13:30:58 via Website

Du lädst die informationen aus der txt Datei in den Listudapeter die du als Referenze dem Listview übergeben hast.
Somit sollte nach einen Refresh des Listviews dieser wieder aktuell sein.

— geändert am 08.04.2014, 13:31:10

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 13:35:10 via App

Und wie führe ich diesen refresh durch?

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 13:54:37 via App

Der Service aktualisiert die txt.

Dann habe ich bereits einen handler eingebaut in die activity mit der listview der alle 10 Sekunden ein notifydatasetchanged aufruft.

Jedoch wenn ich die txt aktualisiere passiert in der laufenden activity nichts refresh technisch.

Antworten
Fabian Simon
  • Forum-Beiträge: 359

08.04.2014, 14:11:57 via Website

Ja dein Listadapter muss sich verändern, damit notifyDataSetChange ne wirkung hat.

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 14:19:11 via App

Inwiefern ändern?

Antworten
Fabian Simon
  • Forum-Beiträge: 359

08.04.2014, 14:48:51 via Website

Ich weiß ja nicht was du gemacht hast...
aber normalerweise hat der Listadapter eine Anzahl an elementen.
Wenn nun notifyDataSetChange aufgerufen wird, werden wieder die methoden des Listadapter ausgeführt.
z.B. so :

1private class MeinListAdapter extends ArrayAdapter{
2
3 private Context context;
4 private int id;
5 private List<String> items;
6 public MeinListAdapter (Context context, int textViewResourceId,
7 String[] objects) {
8 super(context, textViewResourceId, objects);
9 this.context = context;
10 this.id = textViewResourceId;
11
12 this.items = new ArrayList<String>();
13 for(String one : objects){
14 this.items.add(one);
15 }
16 }
17 @Override
18 public View getView(int position, View view, ViewGroup parent) {
19 if (view == null){
20
21 LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
22 view = vi.inflate(id, null);
23 }
24 TextView text = (TextView)view.findViewById(R.id.menu_list_view_text);
25 if (items.get(position) != null){
26 text.setTextColor(Color.WHITE);
27 text.setText(items.get(position));
28 }
29 return view;
30 }
31 }

Somit müsste wenn du in dem Bespiel die variable items z.B.: um einen wert ergänzt nach notifyDataSetChange dies auch angezeigt werden.

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 14:53:22 via Website

Ich habe das Problem an folgendem Punkt:

1FileInputStream in = new FileInputStream(chatfile);
2
3 InputStreamReader input = new InputStreamReader(in);
4 BufferedReader buffreader = new BufferedReader(input);
5
6
7
8 while((line=buffreader.readLine()) != null){
9
10 String[] lineseperated = line.split(";");
11
12 String versendername = lineseperated[0];
13 String nachricht = lineseperated[1];
14 String zeit = lineseperated[2];
15
16 HashMap<String, Object> map = new HashMap<String, Object>();
17
18 map.put("versendername", versendername);
19 map.put("zeit", zeit);
20 map.put("nachricht", nachricht);
21
22
23
24 ListAdapter adapter = new SimpleAdapter(getActivity()
25 .getBaseContext(), chatlist, R.layout.chatitem,
26 new String[] { "versendername" , "zeit" , "nachricht"},
27 new int[] { R.id.chatname, R.id.time , R.id.nachri});
28 chatlist.add(map);
29
30
31
32
33 setListAdapter(adapter);

Hier wird über den Adapter die Listview gefüllt.

nun habe ich in der offline Datei per Service eine neue Zeile die auszulesen ist.

Wie aktualisiere ich die LV wenn die Activity im Vordergrund ist?

Antworten
Fabian Simon
  • Forum-Beiträge: 359

08.04.2014, 15:02:28 via Website

schau dir mal FileObserver an...
Vielleicht löst das dein Problem

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 15:34:25 via Website

Vielen Dank dafür!

Nun kann ich schonmal erkennen wenn die txt vom Service verändert wurde.

Leider weiß ich dann immernoch nicht wie ich wenn die datei geändert wurde nun die Listview aktualisiere.

:( langsam verzweifel ich.

Antworten
Fabian Simon
  • Forum-Beiträge: 359

08.04.2014, 15:37:11 via Website

Im schlimmsten fall machst ein erneutes .setListViewAdapter...

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 15:38:43 via Website

Also eine erneute Funktion mit setListAdapter()?

Wie sollte diese dann ungefähr aussehen?

Wie die oben beschriebene?

Antworten
Fabian Simon
  • Forum-Beiträge: 359

08.04.2014, 15:48:25 via Website

Ja das sollte denk ich funktionieren. aber eig müsste das mim notifyDataSetChange auch gehen, wenn du halt die Referenze auf den Array im Adapter behälst oder den Adapter selber schreibst.

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 16:51:20 via Website

Habe es jetzt geschafft =)

Durch eine neue Methode "refreshnow" wird einfach die Datei erneut ausgelesen und der adapter neu gesetzt.

1public void refreshnow(){
2
3
4 try{
5 File chatfile = new File(Environment.getExternalStorageDirectory() + "xxxxxxxxxxx");
6
7 String line = "";
8
9 FileInputStream in = new FileInputStream(chatfile);
10
11 InputStreamReader input = new InputStreamReader(in);
12 BufferedReader buffreader = new BufferedReader(input);
13
14 while((line=buffreader.readLine()) != null){
15
16 String[] lineseperated = line.split(";");
17
18 String versendername = lineseperated[0];
19 String nachricht = lineseperated[1];
20 String zeit = lineseperated[2];
21
22 HashMap<String, Object> map = new HashMap<String, Object>();
23
24 map.put("versendername", versendername);
25 map.put("zeit", zeit);
26 map.put("nachricht", nachricht);
27
28
29
30 adapter = new SimpleAdapter(getActivity()
31 .getBaseContext(), chatlist, R.layout.chatitem,
32 new String[] { "versendername" , "zeit" , "nachricht"},
33 new int[] { R.id.chatname, R.id.time , R.id.nachri});
34 chatlist.add(map);
35
36
37
38
39 setListAdapter(adapter);
40
41
42
43
44 }
45
46 buffreader.close();
47
48
49
50 }catch(Exception e){
51 Log.e("Error in refresh", e.toString());
52 }
53
54
55
56}


Das ganze lade Ich dann alle 5Sekunden über einen Handler und siehe da, es klappt!

1final Handler handler = new Handler();
2 handler.postDelayed( new Runnable() {
3
4 @Override
5 public void run() {
6
7 Log.i("tick", "tick");
8 refreshnow();
9 handler.postDelayed( this, 5000);
10
11 }
12 }, 5000 );

Vielen Dank für die Gute Unterstützung :)!!!!

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

08.04.2014, 19:35:11 via Website

Doch noch ein Problem :(.

Ich habe meine Funktion:

1public void refreshnow(){
2
3
4 try{
5 File chatfile = new File(Environment.getExternalStorageDirectory() + "XXXXXXXXX");
6
7 String line = "";
8
9 FileInputStream in = new FileInputStream(chatfile);
10
11 InputStreamReader input = new InputStreamReader(in);
12 BufferedReader buffreader = new BufferedReader(input);
13
14 while((line=buffreader.readLine()) != null){
15
16 String[] lineseperated = line.split(";");
17 setListAdapter(null);
18 String versendername = lineseperated[0];
19 String nachricht = lineseperated[1];
20 String zeit = lineseperated[2];
21
22 HashMap<String, Object> map = new HashMap<String, Object>();
23
24 map.put("versendername", versendername);
25 map.put("zeit", zeit);
26 map.put("nachricht", nachricht);
27
28
29
30
31
32 adapter = new SimpleAdapter(getActivity()
33 .getBaseContext(), chatlist, R.layout.chatitem,
34 new String[] { "versendername" , "zeit" , "nachricht"},
35 new int[] { R.id.chatname, R.id.time , R.id.nachri});
36 chatlist.add(map);
37
38
39
40
41
42 setListAdapter(adapter);
43
44
45
46
47 }
48
49 buffreader.close();
50
51
52
53 }catch(Exception e){
54 Log.e("Error in refresh", e.toString());
55 }
56
57
58
59}

Ich habe nun meinen ListAdapter global definiert.

Problem ist folgendes:

Die txt wird komplett ausgelesen und in den Adapter geschrieben bzw. an die Listview übergeben.
Nun passiert in der refreshnow() genau das selbe nochmal.

Nun kriege ich alle Einträge alle 5 Sekunden doppelt, dann dreifach, dan vierfach usw. aufgrund von:

1final Handler handler = new Handler();
2 handler.postDelayed( new Runnable() {
3
4 @Override
5 public void run() {
6
7 Log.i("tick", "tick");
8
9 refreshnow();
10
11
12 handler.postDelayed( this, 5000);
13
14 }
15 }, 5000 );

Demzufolge liegt es wahrscheinlich an der globalen Adapter Variable.
Wie clear() ich sowas?


Hiiiiilfee! :(

Antworten
Fabian Simon
  • Forum-Beiträge: 359

09.04.2014, 08:18:34 via Website

Sorry aber du löst das äußerst kompliziert !
Warum nutzt du jetzt auf einmal doch kein FileObserve mehr sondern machst es alle 5 sekunden einen refresh??
Und schaffst du es endlich mal deinen eigenen Adapter zuschreiben ?
Dann passiert nämlich so ein Blödsinn nicht!
Mein Vorschlag ist :
Listview hat deinen ListAdapter (den von dir selbst entwickelten indem du erbst)
In dem erstelltst du einen Methode refresh oder so...
Diesen ListAdapter merkst du dir global.

Wenn FileObserve anschlägt, wird die Methode refresh im Adapter aufgerufen und im Anschluss das Listview angewiesen neu zu laden.

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

10.04.2014, 15:39:03 via Website

Soo habs hinbekommen aber stehe noch vor einem kleinen (wie ich hoffe) Problem.

In meiner Offline Datei stehen Die Nachrichten Zeile für Zeile.

Problem ist das wenn eine Nachricht eingetragen wird welche einen Zeilenumbruch hat.

Dann sieht es so aus:

1Username;Nachricht;DatumUhrzeit
2Username;Nachricht;DatumUhrzeit
3Username;Nachricht;DatumUhrzeit
4Username;Nachricht;DatumUhrzeit
5Username;Nachricht;DatumUhrzeit
6Username;Nachricht
7
8Nachricht Abschnitt 2 ;DatumUhrzeit
9Username;Nachricht;DatumUhrzeit

Nun bekomme ich da ich die ausgelesene Zeile mit der .split(";") Funktion in Username, Nachricht und Datum geteilt wird eine ArrayIndexOutOfBoundsException.

Logcat:

1E/error(18631): FEHLERBERICHT IN PARSINF: java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
2E/SpannableStringBuilder(18631): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
3E/SpannableStringBuilder(18631): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
4E/error(18631): FEHLERBESCHREIBUNGjava.lang.ArrayIndexOutOfBoundsException: length=2; index=2
5E/error(18631): FEHLERBERICHT IN PARSINF in Updateservice!: java.lang.NullPointerException
6D/dalvikvm(18631): GC_FOR_ALLOC freed 3204K, 18% free 15905K/19176K, paused 40ms, total 41ms

Antworten
impjor
  • Forum-Beiträge: 1.793

10.04.2014, 15:47:09 via App

Das liegt daran, dass du die Datei zeilenweise ausliest und die entsprechende Zeile nur Name und Nachricht enthält. Greifst du auf DatumUhrzeit zu schlägt das fehl, da das nicht mehr in der Zeile ist.

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

10.04.2014, 15:50:41 via Website

Es geht um eine Chat Applikation welche aus der Offline Datei versorgt wird.

Wie kann ich die Zeilenumbrüche am einfachsten behalten (da Sie ja zu einer Chat Nachricht dazu gehören)?

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

10.04.2014, 17:53:36 via Website

Entweder du kodiest diese in die Textdatei hinein (zb. als \n) oder du verwendest Sonderzeichen und ersetzt dies beim Laden durch ein Zeilenumbruch

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

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

10.04.2014, 17:55:37 via App

Auf die Idee war ich gerade auch gekommen :D

Habe via replaceall() die "\n" durch ""#" ersetzt und umgekehrt :))

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

10.04.2014, 17:59:47 via Website

Wenn jetzt aber jemand als Nachricht "#" schreibt zb als hashtag dann siehst du das offline nicht mehr.
Du könntest irgendwas kryptschen verwenden wie:
^24y° oder so

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

Antworten
Bastian Seidemann
  • Forum-Beiträge: 137

10.04.2014, 18:02:11 via Website

Guter Einwand, setze ich um =)

Vielen Dank!

Antworten
impjor
  • Forum-Beiträge: 1.793

10.04.2014, 18:07:59 via Website

Edit: Hab etwas länger geschrieben, Pascal hat ja schon eine Lösung und deren Nachteile aufgezählt.
Das Problem mit dem Semikolon bleibt aber.
---
Du solltest dir überlegen, die Nachrichten in einer Datenbank abzulegen.
Stell dir vor ein User schreibt eine Nachricht mit Semikolon, dann wird eine schöne Strucktur ebenfalls zerstört.

Ich würde ganz anders vorgehen und es so lösen: Der Aufbau der Datei wird wie folgt verändert:
Username;DatumUhrzeit;Anzahl Zeichen der Nachricht;Eine Nachricht mit ; und
mehreren
ZeilenumbrüchenUsername;DatumUhrzeit;Anzahl Zeichen;Eine neue Nachricht ohne ZeilenumbruchUsername;DatumUhrzeit;Anzahl Zeichen;Weitere Nachricht
Heißt, Alle Informationen werden hintereinander geschrieben, ohne Zeilenumbruch. Vor der Nachricht wird die Länge ebendieser gespeichert. Dein Programm müsste dann zuerst alle Zeichen bis zum Semikolon lesen (Username), dann wieder alle bis zum Semikolon (DatumUhrzeit), dann nochmals alle bis zum Semikolon (Anzahl der Zeichen) und dann eben genau die "Anzahl der Zeichen" Zeichen einlesen. Dann fängts wieder von vorne an. So hast du alle Probleme (Zeilenumbruch, Semikolon in Nachricht etc.) umgangen. Nur der Nutzername darf dann kein Semikoln enthalten.

— geändert am 10.04.2014, 18:09:33

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten