Globale TextView Variable

  • 18 Antworten
  • Neuester Beitrag
Diskutiere Globale TextView Variable im Android App Entwicklung im Bereich Betriebssysteme & Apps.
swa00

swa00

Moderator
Teammitglied
Hallo liebe Gemeinde,

ich entwickle zwar schon über 20 Jahre in C++ aber bei so manchen Dingen im Android SDK bekomme ich nicht so hin , wie ich mir das vorstelle :)

Ich habe das Problem ,dass ich in Timer Routinen oder einem Thred keinen Zugriff mehr auf eine TextView Variable habe, warum nicht ? ( null)


mach ich folgendes bei einem Callback des GPS sensors
TextView tview = (TextView) findViewById(R.id.textfeld);
tview.setText("Bla Bla");
alles Prefekt !!!


Habe ich z.b einen Timer
class UpdateTimeTask extends TimerTask
{
public void run()
{
long millis = System.currentTimeMillis() - 200;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
TextView tview = (TextView) findViewById(R.id.textfeld);
tview.setText("Bla bla");
}
}

oder in einem Thread
@Override
public void run()
{
try
{

while(true)
{
sleep(1000);
TextView tview = (TextView) findViewById(R.id.textfeld);
tview.setText("Bla Bla");

}
}
catch(InterruptedException e){}
}



dann bekomme ich einen Vollabsturz beim zugriff auf den TextView
Den gibt es einfach nicht

Ich kann machen was ich will , also Globale variable , local etc etc .. immer in einem Thread oder in einem Time habe ich keinen Zugriff mehr auf Texview

Warum ist das so, oder was mache ich grundsätzlich falsch in meinem Überlegungen ?

Vielen lieben Dank mal im Voraus für euere Antworten
lg
Stefan

gegeben : Android SDK unter Eclipse
 
GalaxyKeks

GalaxyKeks

Experte
Wie lautet denn die Fehlermeldung?
Vielleicht kannst du mal den Stacktrace posten und die dort verlinkten Zeilen...
 
swa00

swa00

Moderator
Teammitglied
Hi Galaxy,

danke für deine schnelle Antwort und schon hast du mich auf dem mega falschen Fuss erwischt :)

Wie erstelle ich den von dir erwünschten Stacktrace unter Eclipe ?

lg
Stefan
 
swa00

swa00

Moderator
Teammitglied
03-29 08:53:23.337: ERROR/AndroidRuntime(660): FATAL EXCEPTION: Thread-8
03-29 08:53:23.337: ERROR/AndroidRuntime(660): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.view.ViewRoot.checkThread(ViewRoot.java:2802)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.view.ViewRoot.invalidateChild(ViewRoot.java:607)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:633)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2505)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.view.View.invalidate(View.java:5139)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.widget.TextView.checkForRelayout(TextView.java:5364)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.widget.TextView.setText(TextView.java:2688)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.widget.TextView.setText(TextView.java:2556)
03-29 08:53:23.337: ERROR/AndroidRuntime(660): at android.widget.TextView.setText(TextView.java:2531)


Sagt das was ? :)


P.S danke für die Newbie unterstüzung :)
 
GalaxyKeks

GalaxyKeks

Experte
Kein Thema, jeder fängt mal an ;)
Ist das alles was der ausspuckt?

Und noch eine andere Frage:
Warum hast du
TextView tview = (TextView) findViewById(R.id.textfeld);
Mit in der Schleife? reicht doch das einmal da drüber raus zu holen, da ändert sich ja nichts...

Und beide Varianten gehen nicht?
 
swa00

swa00

Moderator
Teammitglied
also ich portioniere mal , damit es übersichtlicher wird ..

innerhalb public void onCreate(Bundle savedInstanceState)
{
... bla bla bla init
// Mal nen Test .... geht
TextView tview = (TextView) findViewById(R.id.textfeld);
tview.setText("Hallo");

// thread starten
StartCalculateThread();

}


// hier der Thread
//////////////////////////////////////
public void StartCalculateThread()
{
// thread für die Berechnung
Thread CalculateThread = new Thread()
{
@Override
public void run()
{

TextView tview = null;
tview = (TextView) findViewById(R.id.textfeld);
try
{
while(true)
{
sleep(1000);
tview.setText("Bla Bla");

}
}
catch(InterruptedException e){}
}
};
CalculateThread.start();
/////////////////////////////

Die Stacktrace zeilen habe ich natürlich erst ab der Exception herauskopiert - bin nicht davon ausgegangen , dass du das ganze geraffel haben wolltest :)

lg
 
GalaxyKeks

GalaxyKeks

Experte
Dein
... bla bla bla init
wäre noch interessant, weil du das ContentView setzten musst.

Wegen dem Logcat ist, wollte nicht alles ;)
Aber wundert mich das der nirgends auf deinen Code verweist...
 
garak

garak

Ehrenmitglied
swa00 schrieb:
Only the original thread that created a view hierarchy can touch its views.
Das ist doch ziemlich eindeutig. Wenn du einen TimerTask erstellst, bekommst du einen neuen Thread und der kann nicht auf ein View eines anderen Threads zugreifen. Abhilfe könnte schaffen das TextView als public static zu deklarieren und über die Startklasse darauf zuzugreifen, aber ob das funktioniert musst du selber herausfinden:

Code:
public class StartKlasse extends Activity {
  public static TextView tview;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    tview = (TextView) findViewById(R.id.textfeld);
    ...
  }
  ....
}

////////////////////////

class UpdateTimeTask extends TimerTask {
   public void run() {
      ...
      StartKlasse.tview.setText("Bla bla");
   }
}
 
swa00

swa00

Moderator
Teammitglied
public void onCreate(Bundle savedInstanceState)
{

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);
// hide statusbar of Android
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
setContentView(R.layout.main);



// GPS listener einschalten
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener()
{
public void onLocationChanged(Location location) {GetGPS (location);}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}

};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);


// Start Thread
StartCalculateThread();





}

Übrigens - zur Info : Das geht also der Callback des Sensors

///////////////////////////////////////////////////////////////////////////////////////////////////
public void GetGPS (Location location)
{
GlobalVars.LAT = location.getLatitude();
GlobalVars.LON = location.getLongitude();
GlobalVars.ALT = location.getAltitude();
GlobalVars.DIRECTION = location.getBearing();
GlobalVars.SPEED = location.getSpeed();


DecimalFormat f = new DecimalFormat("#0.00");

String Text = "Aktuelle Position:\n" +"Latitude = " + GlobalVars.LAT+
"\nLongitude = " + GlobalVars.LON+
"\nSpeed km/h = " + f.format((GlobalVars.SPEED/3.6)/1000)+
"\nAlt = " + GlobalVars.ALT+
"\nRichtung = " + waited;//GlobalVars.DIRECTION;

TextView tview = (TextView) findViewById(R.id.textfeld);
//TextView tview = new TextView(this);
tview.setText(Text);
//tview.setLayoutParams(new AbsoluteLayout.LayoutParams(200,100, 250,250));


}










DU HAST ES GEWOLLT :)


03-29 09:28:08.277: DEBUG/AndroidRuntime(359): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
03-29 09:28:08.277: DEBUG/AndroidRuntime(359): CheckJNI is ON
03-29 09:28:08.498: DEBUG/AndroidRuntime(359): --- registering native functions ---
03-29 09:28:09.366: INFO/ActivityManager(59): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.streetlimit/.StreetLimit }
03-29 09:28:09.468: DEBUG/AndroidRuntime(359): Shutting down VM
03-29 09:28:09.487: INFO/ActivityManager(59): Start proc com.example.streetlimit for activity com.example.streetlimit/.StreetLimit: pid=365 uid=10040 gids={}
03-29 09:28:09.507: DEBUG/dalvikvm(359): Debugger has detached; object registry had 1 entries
03-29 09:28:09.597: INFO/AndroidRuntime(359): NOTE: attach of thread 'Binder Thread #3' failed
03-29 09:28:09.817: DEBUG/dalvikvm(33): GC_EXPLICIT freed 270 objects / 10312 bytes in 265ms
03-29 09:28:09.967: DEBUG/dalvikvm(33): GC_EXPLICIT freed 32 objects / 1408 bytes in 101ms
03-29 09:28:10.268: DEBUG/dalvikvm(33): GC_EXPLICIT freed 2 objects / 64 bytes in 302ms
03-29 09:28:10.606: WARN/GpsLocationProvider(59): Duplicate add listener for uid 10040
03-29 09:28:11.077: INFO/ActivityManager(59): Displayed activity com.example.streetlimit/.StreetLimit: 1604 ms (total 1604 ms)
03-29 09:28:11.566: WARN/dalvikvm(365): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): FATAL EXCEPTION: Thread-8
03-29 09:28:11.566: ERROR/AndroidRuntime(365): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.view.ViewRoot.checkThread(ViewRoot.java:2802)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.view.ViewRoot.invalidateChild(ViewRoot.java:607)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:633)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.view.ViewGroup.invalidateChild(ViewGroup.java:2505)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.view.View.invalidate(View.java:5139)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.widget.TextView.checkForRelayout(TextView.java:5364)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.widget.TextView.setText(TextView.java:2688)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.widget.TextView.setText(TextView.java:2556)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at android.widget.TextView.setText(TextView.java:2531)
03-29 09:28:11.566: ERROR/AndroidRuntime(365): at com.example.streetlimit.StreetLimit$2.run(StreetLimit.java:213)
03-29 09:28:11.598: WARN/ActivityManager(59): Force finishing activity com.example.streetlimit/.StreetLimit
03-29 09:28:17.418: DEBUG/dalvikvm(188): GC_EXPLICIT freed 242 objects / 16144 bytes in 67ms
03-29 09:28:22.487: DEBUG/dalvikvm(262): GC_EXPLICIT freed 2070 objects / 148040 bytes in 95ms
 
GalaxyKeks

GalaxyKeks

Experte
Versuch mal Garak's Ansatz, da wollte ich übrigens auch drauf hinaus ;)
Du kannst auch ne "Holder-klasse" machen die all das als statische Elemente enthält.
Ist im Prinzip das bloß ausgelagert.

Der Fehler schein von hier : StreetLi mit.java:213 zu kommen.
 
swa00

swa00

Moderator
Teammitglied
Halllo Garak,

danke für Deine Idee...


garak schrieb:
Das ist doch ziemlich eindeutig. Wenn du einen TimerTask erstellst, bekommst du einen neuen Thread und der kann nicht auf ein View eines anderen Threads zugreifen. Abhilfe könnte schaffen das TextView als public static zu deklarieren und über die Startklasse darauf zuzugreifen, aber ob das funktioniert musst du selber herausfinden:

Code:
public class StartKlasse extends Activity {
  public static TextView tview;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    tview = (TextView) findViewById(R.id.textfeld);
    ...
  }
  ....
}

////////////////////////

class UpdateTimeTask extends TimerTask {
   public void run() {
      ...
      StartKlasse.tview.setText("Bla bla");
   }
}

Ich habe s ausprobiert - leider mit dem gleichen Ergebnis ..
Zumal der Thread innerhalb der activity ( oder timer) deklariert ist :-(
 
swa00

swa00

Moderator
Teammitglied
GalaxyKeks schrieb:
Versuch mal Garak's Ansatz, da wollte ich übrigens auch drauf hinaus ;)
Du kannst auch ne "Holder-klasse" machen die all das als statische Elemente enthält.
Ist im Prinzip das bloß ausgelagert.

Der Fehler schein von hier : StreetLi mit.java:213 zu kommen.
Jaaaaaa, ich weis ich nerve .. ne Holder klasse habe ich auch schon hinter mir ....

iste s denn überhaupt richtig , innerhalb der activity alles zu deklarieren ? ich bin im prinzip dadurch gar nicht auf garaks idee gekommen ....
 
garak

garak

Ehrenmitglied
Doch vom Android-Gedanken her schon. Hast du die Timerklasse mal als innere Klasse deines Activities versucht?

Nachtrag: Als innere Klasse funktioniert es:
Code:
public class Test extends Activity {

  private TextView textView1;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    textView1 = (TextView) findViewById(R.id.textView1);
    new TestThread().start();
  }
  class TestThread extends Thread {
    @Override
    public void run() {
      textView1.setText("Bla bla");
    }
  }
}
 
swa00

swa00

Moderator
Teammitglied
Moderation: Nicht den ganzen vorherigen Beitrag zitieren!

soooo, da habe ich jetzt ausprobiert .. negativ

ich frage mal am besten ganz anders - im prinzip möchte ich ja nur alle x sekunden ein Update UI haben, welches daten aus einer Holder klasse anzeigt.


In welche Richtung muss ich denn mal schauen um ein schönes Beispiel zu bekommen , im Prinzip ist das ja eigentlich ziemlich trivial , was ich vorhabe ..

Lieben Dank
Stefan
 
GalaxyKeks

GalaxyKeks

Experte
Vielleicht solltest du etwas banaler anfangen und dann das ganze erweitern wenn es funktioniert ;)
 
swa00

swa00

Moderator
Teammitglied
GalaxyKeks schrieb:
Vielleicht solltest du etwas banaler anfangen und dann das ganze erweitern wenn es funktioniert ;)
ich neige dazu , dir eben 100 Punkte für die Motivation zu vergeben :)
Im Ernst - dass ich an der Hürde scheitere, einfach einen Text an eine simple stelle auszugeben, hätte ich mir nie erträumen lassen :)
 
GalaxyKeks

GalaxyKeks

Experte
swa00 schrieb:
ich neige dazu , dir eben 100 Punkte für die Motivation zu vergeben :)
Im Ernst - dass ich an der Hürde scheitere, einfach einen Text an eine simple stelle auszugeben, hätte ich mir nie erträumen lassen :)
Ich helfe gern, bloß bin ich an der Arbeit und kann nichts testen... daher ist es mehr oder weniger "nur" Spekulation meinerseits.
Generell kann ich dir aber zu so Problemen "Stackoverflow.com" empfehlen, bin da auch aktiv. Da wird auch immer gern und schnell geholfen! :)
 
swa00

swa00

Moderator
Teammitglied
LÖSUNG !!!!

ok, ich bin diesem Forum temporär abtrünnig geworden und habe mich bei StackOverflow umgeshen.

Dieses Beispiel ist die Lösung und sollte fairerweise diesem Forum nicht vorenthalten werden

How to run a Runnable thread in Android? - Stack Overflow

Fazit- ein Thread und ein Timer benötigt einen zusätzlichen Handler um auf Ui Elemente zuzugreifen .


Garak & GalaxyKeks

Vielen lieben Dank für eure Mühe !!!!!!


lg
Stefan