Announcement

Collapse
No announcement yet.

Textview refresh

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Textview refresh

    Hallo,
    ich habe folgendes Problem, das ich wie folgt verkürzen kann:

    Status.setText("Start");
    FunktionXYZ();
    Status.setText("Fertig");

    Wenn ich meine Anwendung starte, soll das Wort "Start" ausgegeben werden. Die Funktion dauert ein paar Sekunden.
    Zum Schluß soll dann "Fertig" angezeigt werden.

    Das Wort "Start" erscheint aber nie.

    In C# oder VB würde ich das wie folgt lösen:
    Status.setText("Start");
    Application.DoEvents(); FunktionXYZ();
    Status.setText("Fertig");

    oder in Delphi
    Status.setText("Start");
    Application.ProcessMessages;
    FunktionXYZ();
    Status.setText("Fertig");

    Diese Befehle gibt es wohl in Java nicht. Nach einiger Googlelei habe ich den Hinweis gefunden, dass nur
    ein zweiter Thread das Glück bringen kann. Also habe ich folgendes probiert:

    Ich habe einen 2. Thread erzeugt:

    class SimpleThread extends Thread
    {
    public static TextView Status;
    public SimpleThread(String str, TextView Anzeige)
    {
    super(str);
    Status = Anzeige;
    }

    synchronized public void run()
    {
    Status.setText(getName());
    }
    }

    In meinen eigentlichen Anwendung rufe ich das wie folgt auf:

    Status = (TextView) findViewById(R.id.txtStatus);
    SimpleThread Show = new SimpleThread("Start", Status);
    Show.start();
    Show.run();

    FunktionXYZ();

    Show = new SimpleThread("Ende", Status);
    Show.start();
    Show.run();

    Gebracht hat das aber nichts. Das Wort "Ende" erscheint, "Start" erscheint immer noch nicht.
    Merkwüdig, bin ich der erste Mensch der soetwas versucht?

    Freue mich auf Antworten und vor allem eine Lösung

  • #2
    Du solltest die Funktion in einen eigenen Thread auslagern.

    Ursache ist folgende:
    - du willst mit setText "Start" ausgeben
    - gleich danach startet deine Funktion
    - diese blokiert den Hauptthread in dem sie arbeitet und "Start" erscheint nicht
    - ist sie fertig, kann auch der Haupthtread weitermachen und würde "Start" ausgeben wollen. Das macht er auch, wird aber gleich von "Fertig" überschrieben

    Kannst du testen. Nimm das "Fertig" raus und es erscheint zum Schluß, wenn die Funktion zu Ende ist "Start"

    Sofern in Android verfügbar ist der Swingworker dafür eine Lösung, sonst wie gesagt die Funktion in einen anderen Thread
    Christian

    Comment


    • #3
      Danke für die Anwort, aber das ist mir ja schon bewußt gewesen. Sonst
      hätte ich den Kram mit DoEvents und ProcressMessage nicht geschrieben.

      Und die Sache mit dem 2. Thread habe ich ja gemacht. Und spätestens dort weiß ich nun nicht mehr weiter.
      "SimpleThread" ist doch ein 2. Thread und trotzdem verhindert "FunktionXYZ" wieder die Ausgabe des
      Wortes "Start"
      Oder mache ich da etwas falsch????

      Comment


      • #4
        Und die Sache mit dem 2. Thread habe ich ja gemacht.
        Ja, aber nicht mit der Funktion, sondern du versuchst deinen Hauptthread in einen zweiten zu packen.

        Beispiel mit Standard-Java. ein Frame mit einem Button und einem Label.

        [highlight=java]
        public class NewJFrame extends javax.swing.JFrame
        {
        public NewJFrame()
        {
        initComponents();
        }

        @SuppressWarnings("unchecked")
        private void initComponents()
        {
        jButton1 = new JButton();
        jLabel1 = new JLabel();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_C LOSE);
        ResourceBundle bundle = ResourceBundle.getBundle("Bundle"); // NOI18N
        jButton1.setText(bundle.getString("NewJFrame.jButt on1.text")); // NOI18N
        jButton1.addActionListener(new ActionListener()
        {
        public void actionPerformed(ActionEvent evt)
        {
        jButton1ActionPerformed(evt);
        }
        });
        jLabel1.setText(bundle.getString("NewJFrame.jLabel 1.text")); // NOI18N
        GroupLayout layout = new GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
        layout.createParallelGroup(GroupLayout.Alignment.L EADING)
        .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(jButton1)
        .addGap(18, 18, 18)
        .addComponent(jLabel1, GroupLayout.PREFERRED_SIZE, 233, GroupLayout.PREFERRED_SIZE)
        .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
        layout.createParallelGroup(GroupLayout.Alignment.L EADING)
        .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(GroupLayout.A lignment.BASELINE)
        .addComponent(jButton1)
        .addComponent(jLabel1))
        .addContainerGap(57, Short.MAX_VALUE))
        );
        pack();
        }
        private void jButton1ActionPerformed(ActionEvent evt)
        {
        setLabelText("Start");
        NewThread nt=new NewThread(this);
        nt.start();
        }

        public void setLabelText(String text)
        {
        jLabel1.setText(text);
        }

        public static void main(String args[])
        {
        java.awt.EventQueue.invokeLater(new Runnable()
        {
        public void run()
        {
        new NewJFrame().setVisible(true);
        }

        });
        }
        private JButton jButton1;
        private JLabel jLabel1;
        [/highlight]

        Bei Druck auf den Button wird eine neuer Thread gestartet und die Meldung "Start" ausgegeben. Dem Thread wird die Instanz des Frames mitgegeben. Ist er fertig, ruft er eine Methode der Frameklasse auf und setzt dort "Fertig"

        [highlight=java]
        public class NewThread extends Thread
        {
        private NewJFrame nj;

        public NewThread(NewJFrame nj)
        {
        this.nj=nj;
        }

        @Override
        public void run()
        {
        try
        {
        Thread.sleep(5000);
        }
        catch(InterruptedException ex)
        {
        ex.printStackTrace();
        }
        nj.setLabelText("Fertig");
        }

        }


        [/highlight]
        Christian

        Comment


        • #5
          Danke, das muss ich mir erst einmal näher ansehen, da ich ein Java Anfänger bin.
          Diesen Aufwand muß man betreiben, um zwischendurch etwas zu aktualisieren? Jede Progressbar usw.
          Kaum zu glauben aber wohl war.

          Swing gibt es unter Android offensichtlich nicht.
          Zuletzt editiert von FoxMan; 05.08.2013, 20:25.

          Comment


          • #6
            Sicher nicht, aber das Prinzip sollte deutlich werden. Ggf. sollte sich die Suche nach "android Swingworker" lohnen, ob ähnliche Implementationen vorliegen
            Christian

            Comment


            • #7
              Also eigentlich verstehe ich nicht, wieso meine Threadlösung nicht funktioniert.

              So oder so ähnlich erzeuge ich in Delphi oder C# auch Threads.

              Status = (TextView) findViewById(R.id.txtStatus);
              SimpleThread Show = new SimpleThread("Start", Status);
              Show.start();
              Show.run();

              Und das dieser Thread läuft, kann ich sehen, wenn ich den Rest darunter entferne. Dann wird "Start" ausgegeben.
              Wenn ich in dem Thread eine Endlosschleife programmiere, bleibt das Programm dann im Thread stehen.

              Welchen Sinn hat das Anlegen eines Threads überhaupt.? Oder versuche ich das, was ich von Delphi oder C# kenne,
              auf Java zu übertragen und in Java hat das eine ganz andere Bedeutung.???
              Meine Threadklasse sieht übrigens wie folgt aus. Ist dort schon ein Mangel so sehen?

              class OutputThread extends Thread
              {
              public static TextView Status;
              public OutputThread(String str, TextView Anzeige)
              {
              super(str);
              Status = Anzeige;
              }

              synchronized public void run()
              {
              Status.setText(getName());
              }
              }
              Zuletzt editiert von FoxMan; 06.08.2013, 05:02.

              Comment


              • #8
                Um es nochmal zu wiederholen:

                Dein Thread - der die GUI aktualisieren soll - läuft aber nicht im Context der GUI. Selbst wenn der Thread den Status erneuert, ist die GUI immer noch mit deiner Funktion beschäftigt und kann - die vom Thread kommende Aufforderung - den status zu aktualisieren nicht erfüllen. Der Hauptthread ist mit deiner Funktion beschäftigt.
                Du musst deine Funktion in einen Thread auslagern.

                Schon der erste Treffer mit meiner o.a. Suche bringt dich auf http://developer.android.com/referen...AsyncTask.html

                Die Technik der der Thread vs. GUI ist im Delphi, C#, C++Builder gleich. Bei der VCL hast du halt die Möglichkeit ein ProcessMessage aufzurufen. In Java nicht. Dort gibt es den SwingWorker und in Android den AsyncTask
                Zuletzt editiert von Christian Marquardt; 06.08.2013, 08:03.
                Christian

                Comment


                • #9
                  Sorry, aber entweder ich bin zu blöd oder wir reden völlig aneinander vorbei.

                  In meinem Beispiel starte ich einen Thread. Ich glaube zumindest, dass das so ist. Da ich absoluter Java
                  Anfänger bin, könnte ich mir vorstellen, dass ich dabei etwas falsch mache. Aber das Ding startet und
                  gibt auch etwas aus.

                  In anderen Sprachen wie C# ist es völlig egal, was im Code darunter steht, wenn im 2. Thread eine Endlosschleife
                  steht, dann arbeitet das Ding ohne Ende. Was wäre das für ein Thread, wenn ich ihn durch einen anschließenden
                  Funktionsaufruf anhalten kann.

                  In meinem Beispiel ist es egal, ob meine Arbeit direkt dahinter aufgerufen wird, oder ob ich das in einen weiteren
                  Thread unterbringe. Das habe ich natürlich probiert, bringt aber nichts.
                  Das Problem ist einfach, dass der Thread für die Ausgabe sich nicht wie ein Thread verhält
                  (damit meine ich wie ein C# Thread) sondern wie eine ganz normale Funktion. Und deshalb geht es nicht.

                  Mit AsyncTask erreiche ich absolut dasselbe Ergebnis.
                  Sicher, wenn ich in Delphi ProcessMessage oder in anderen Sprache DoEvents aufrufe, dann brauche ich den
                  ganzen Zirkus nicht. Würde ich dafür aber auch Threads einsetzen, würde es auch laufen. Nur muss ich über C#
                  über invoke arbeiten oder mir etwas anderes zum threadsicheren Einsatz suchen.

                  Egal was ich jetzt getestet habe, es geht einfach nicht.

                  Kann es daran liegen, dass ich mit einem Emulator arbeite ???? Ein echte Zielmaschine bekomme ich erst in den nächsten Tagen.


                  Danke
                  Zuletzt editiert von FoxMan; 06.08.2013, 18:11.

                  Comment


                  • #10
                    Nein, in keiner Sprache kannst du den Hauptthread einfach anhalten oder blockieren und erwarten, dass GUI-Änderungen einfach so einfließen. Ich weiss nicht, was du mit AsyncTask gemacht hast, aber dein bisherigen Versuche liefen darauf hinaus, duch den 2. Thread die GUI zu ändern, während der Hauptthread durch deine Funktion blockiert war. Blockiert ist blockiert. Da hilft es nichts, duch ein 2. Thread von außen etwas bewirken zu wollen.

                    Der Haupthread ist - egal in welcher Sprache - mit dem Betriebssystem verbunden und nimmt die Nachrichten entgegen. Das kann er nicht, wenn er langwierige Operationen ausführen muss.

                    Warum packst du nicht endlich deine Funktion in den Thread. Der Hauptthread startet den 2. Thread mit der Funktion, gibt "Start" aus und das wars. Ist dein 2. Thread mit der Arbeit fertig, informiert er darüber den Hauptthread. Dieser gibt nun "Ende" aus. Du packst immer die GUI-Ausgabe in den 2. Thread.
                    Christian

                    Comment


                    • #11
                      Wenn ich im Haupthread einen anderen Thread starte, dann ist es diesem anderen Thread egal, was nach dem
                      Starten des Thread passiert. Das wollte ich zum Ausdruck bringen.

                      Ich habe meine Arbeit in eimen zweiten Thread gepackt. Das ändern absolut nichts.

                      Comment


                      • #12
                        Der Code aus #4 zeigt, dass es anders geht. Wie du es gemacht hast, weiss ich nicht
                        Christian

                        Comment


                        • #13
                          Ich habe ein vollständiges lauffähiges Beispiel mit einer graphischen Aushabe gefunden. Also mit meinem Fall durchaus vergleichbar.
                          Das Programm läuft tadellos. Zunächst musste ich nichts ändern. Was es macht, kann man hier sehen
                          http://samir-mangroliya.blogspot.in/...k-example.html

                          Den roten Code habe ich eingefügt. Nun wird das Programm durch meinen zusätzliche Thread aufgehalten.
                          Wenn etwas falsch ist, dann muss es doch das von mir eingefügt Zeugs sein.


                          Code:
                          package com.example.mymultithread;
                          
                          import android.app.Activity;
                          import android.app.AlertDialog;
                          import android.app.Dialog;
                          import android.content.DialogInterface;
                          import android.os.AsyncTask;
                          import android.os.Bundle;
                          import android.view.View;
                          import android.view.View.OnClickListener;
                          import android.view.Window;
                          import android.widget.Button;
                          import android.widget.ProgressBar;
                          import android.widget.TextView;
                          
                          public class MainActivity extends Activity
                          {
                          	Button btnStart;
                          	MyTask objMyTask;
                                        ThreadWork objMyWork;
                          
                          	private static final int SLEEP_TIME=((60*1000)/100);
                          	@Override
                          	public void onCreate(Bundle savedInstanceState) {
                          		super.onCreate(savedInstanceState);
                          		setContentView(R.layout.activity_main);
                          
                                  btnStart = (Button) findViewById(R.id.btnstart);
                          		btnStart.setOnClickListener(new OnClickListener()
                                  {
                          			@Override
                          			public void onClick(View v)
                                      {
                          				objMyTask = new MyTask();
                          				objMyTask.execute();
                          
                                          objMyWork = new ThreadWork();
                                          objMyWork.start();			}
                          		});
                          	}
                          
                          
                              class ThreadWork extends Thread
                              {
                                  public ThreadWork()
                                  {
                                      try
                                      {
                                          Thread.sleep(6000);
                                      }
                                      catch(Exception e)
                                      {
                                      }
                                  }
                              }
                          
                          	class MyTask extends AsyncTask<Void, Integer, Void>
                              {
                          
                          		Dialog dialog;
                          		ProgressBar progressBar;
                          		TextView tvLoading,tvPer;
                          		Button btnCancel;
                          
                          		@Override
                          		protected void onPreExecute()
                                  {
                          			super.onPreExecute();
                          			dialog = new Dialog(MainActivity.this);
                          			dialog.setCancelable(false);
                          			dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                          			dialog.setContentView(R.layout.progressdialog);
                          
                          			progressBar = (ProgressBar) dialog.findViewById(R.id.progressBar1);
                          			tvLoading = (TextView) dialog.findViewById(R.id.tv1);
                          			tvPer = (TextView) dialog.findViewById(R.id.tvper);
                          			btnCancel = (Button) dialog.findViewById(R.id.btncancel);
                          
                          			btnCancel.setOnClickListener(new OnClickListener()
                                      {
                          				@Override
                          				public void onClick(View v)
                                          {
                          					objMyTask.cancel(true);
                          					dialog.dismiss();
                          				}
                          			});
                          
                          			dialog.show();
                          		}
                          
                          		@Override
                          		protected Void doInBackground(Void... params)
                                  {
                          			for (int i = 1; i <100; i++)
                                      {
                          				if (isCancelled())
                                          {
                          					break;
                          				}
                                          else
                                          {
                          					System.out.println(i);
                          					publishProgress(i);
                          					try
                                              {
                          						Thread.sleep(SLEEP_TIME);
                          					} catch (InterruptedException e)
                                              {
                          						e.printStackTrace();
                          					}
                          				}
                          			}
                          
                          			return null;
                          		}
                          
                          		@Override
                          		protected void onProgressUpdate(Integer... values)
                                  {
                          			super.onProgressUpdate(values);
                          			progressBar.setProgress(values[0]);
                          			tvLoading.setText("Loading...  " + values[0] + " %");
                          			tvPer.setText(values[0]+" %");
                          		}
                          
                          		@Override
                          		protected void onPostExecute(Void result)
                                  {
                          			super.onPostExecute(result);
                          
                          			dialog.dismiss();
                          
                          			AlertDialog alert = new AlertDialog.Builder(MainActivity.this)
                          					.create();
                          
                          			alert.setTitle("Completed!!!");
                          			alert.setMessage("Your Task is Completed SuccessFully!!!");
                          			alert.setButton("Dismiss", new DialogInterface.OnClickListener()
                                      {
                          				@Override
                          				public void onClick(DialogInterface dialog, int which)
                                          {
                          					dialog.dismiss();
                          				}
                          			});
                          			alert.show();
                          		}
                          	}
                          
                          }

                          Comment


                          • #14
                            Wozu noch einen Task. Schau dir an, was AsyncTask in welcher Methode macht
                            Christian

                            Comment


                            • #15
                              Stimmt, habe ich gemacht. So geht es
                              Danke

                              Comment

                              Working...
                              X