2012-10-16 21 views
9

ich in meiner Anwendung eine benutzerdefinierte Listview haben, eine Image und 3-5 Textviews enthält.Android: Update Listview Artikel alle 1 Minute

1 der Textviews zeigt den zeitlichen Zwischenraum zwischen dem aktuellen Zeit und demZeit für das Listview-Element spezifiziert.

Like: Gesendet 5 Minuten

Die Frage ist, wie ich diese Textview ohne Störung des Listview jede Minute aktualisieren.

Like: wenn ich für 5 Minuten bei der Listview suchen, gerade diese Textview allein muss von 1 min bis 2 Minuten ändern usw. für jedes Element sichtbar

Was ich versuchte:

  1. dieses Textview in getView set()System.currentTimeMillis() - givenTime[position]; Verwendung

aber hier ist die Textview wird nicht aktualisiert, wenn ich nicht das Scrollen (nicht die getView Aufruf) oder die Sichtbarkeit der Elemente zu verändern.

  1. Verwenden Sie einen Time() Faden alle 1 Minute und versuchen, die Textview jedes Element

hier das Problem zu aktualisieren, erhalte ich eine Ausnahme:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

außerdem i keine Ahnung, wie das Textview für jedes Listview-Element von der Aktivität zu ändern.

Aber das sieht aus wie ein vertrauter Fall.

Wie kann ich das erreichen?

Danke

Antwort

32

ein Handler und seine postDelayed Methode, um die Liste der Adapter ungültig zu machen, wie folgt:

final Handler handler = new Handler() 
handler.postDelayed(new Runnable() { 

    @Override 
    public void run() { 
     adapter.notifyDataSetChanged(); 
     handler.postDelayed(this, 60 * 1000); 
    } 
}, 60 * 1000); 

Sie nur UI in der Haupt (UI) Thread aktualisieren.

Durch den Handler in dem Haupt-Thread erstellen, stellen Sie sicher, dass alles, was man an den Handler Beitrag ist auch im Hauptthread ausgeführt werden.

+1

verwenden aber nicht notifyDataSetChanged(); funktioniert nur, wenn die Daten geändert werden ?? –

+0

Es aktualisiert die Listenansicht, egal ob Daten geändert wurden oder nicht. – Carnal

+0

gut. Es funktionierte. Danke vielmals. Aber was ich dachte, war in der Regel Anwendungen nur das bestimmte TextView nicht das gesamte ListView-Element zu aktualisieren. Führt dies nicht zu Verzögerungen oder einem Einfrieren der Benutzeroberfläche, wenn der ListView-Eintrag zu kompliziert ist? wie wenn es 2-3 Bilder enthält, 3-5 TextViews ?? –

4

Sie können auch benutzerdefinierte TextView erstellen, die sich jede Sekunde oder Minute oder Stunde aktualisiert. Dies kann leicht getan werden, indem Klasse zu schaffen, die TextView und fügen Sie Handler innerhalb dieser Klasse erweitert.Der Vorteil ist, dass Sie Ihre gesamte ListView nicht aktualisieren müssen, TextView wird sich automatisch aktualisieren.

Beispiel:

public class TextViewTimeCounter extends TextView { 
private long mStartTime = 0; 
private long mTimeNow = 0; 
private int mDelay = 0; 
private String mPart1 = ""; 
private String mPart2 = ""; 

private Handler mHandler; 

public TextViewTimeCounter(Context context) { 
    super(context, null, 0); 
} 

public TextViewTimeCounter(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
} 

public TextViewTimeCounter(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
} 

public void startTimer(long delay, String part1, String part2){ 
    mStartTime = System.currentTimeMillis(); 
    mTimeNow = System.currentTimeMillis(); 
    mDelay = delay; 
    mHandler = new Handler(); 
    mHandler.postDelayed(r, delay); 
    convertDatesToMinutes(mStartTime, mTimeNow); 
} 

public void stopTimer(){ 
    if(mHandler != null){ 
     mHandler = null; 
     mStartTime = 0; 
     mTimeNow = 0; 
    } 
} 

public boolean isTimerRunning(){ 
    return mHandler == null? false : true; 
} 


Runnable r = new Runnable() { 
    @Override 
    public void run(){ 
     mTimeNow += mDelay; 
     convertDatesToMinutes(mStartTime, mTimeNow); 
     if(mHandler != null){ 
      mHandler.postDelayed(r, mDelay); 
     } 
    } 
}; 



public void convertDatesToMinutes(long start, long end){ 
    long secs = (end - start); 
    long minute = (secs/(1000 * 60)) % 60; 
    long hour = (secs/(1000 * 60 * 60)) % 24; 
    String time = String.format(Locale.getDefault(), "%2d hours %2d minutes", hour, minute); 

    setText(mPart1 + time + mPart2); 
} 

Verbrauch:

TextViewTimeCounter timer = (TextViewTimeCounter)convertView.findViewById(R.id.start_logging_time_text); 
timer.startTimer(10000, "Posted ", " ago"); 

Ausgabe wie folgt aussehen:

Posted 1 hours 5 minutes ago 

Wenn Sie auch Sekunden angezeigt werden soll, ändern convertDatesToMinutes(long start, long end) Methode dazu:

public void convertDatesToMinutes(long start, long end){ 
     long secs = (end - start); 
     long second = (secs/1000) % 60; 
     long minute = (secs/(1000 * 60)) % 60; 
     long hour = (secs/(1000 * 60 * 60)) % 24; 
     String time = String.format(Locale.getDefault(), "%2d hours %2d minutes %2d seconds", hour, minute, second); 
     setText(mPart1 + time + mPart2); 
} 
+0

Wie würden Sie den Timer in diesem Beispiel stoppen? In der Theorie wäre es nur, wenn die Liste die Ansicht entfernt, aber es sieht nicht so aus, als ob es eine Möglichkeit gäbe, dies zu tun. –

+0

Wenn Sie den benutzerdefinierten Listenadapter verwenden, der BaseAdapter erweitert, müssen Sie ListAdapter.notifyDataSetChanged(); und im Adapter getView(); Methode, die Sie aufrufen stopTimer(); – user1888162

1

Wenn Sie eine Aktion im Hauptthread in den Fraktionen der Zeit wiederholen wollen, sollten Sie „Zeitplan“ Methode des Time.class

mHandler = new Handler(); 
mTimer = new Timer(); 
mTimer.schedule(new TimerTask() { 
    @Override 
    public void run() { 
     mHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       // run main thread code 
      } 
     }); 
    } 
}, DELAY_TIME, PERIOD_TIME);