Dynamisches Diagramm in Sub-Activity (Achartengine) Problem

  • Antworten:30
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 16

25.08.2014, 22:50:19 via Website

Hallo,

ich versuche eine Android-App zu programmieren, der Messwerte in Real-Time erfasst. Die App wird als Sub-Activity ein Diagramm besitzen. Dieses Diagramm habe ich mit Achartengine erstellt und an mein Projekt eingebunden. Das Diagramm wird beim ersten Aufruf perfekt gezeichnet aber sobald ich zum Main-Activity wechsele (Zurück-Button) und wieder in Sub-Activity springe, wird das Diagramm nicht mehr gezeichnet. Komischerweise fehlt auch die Beschriftung der Achsen.

Ich verstehe nun nicht, warum die Initialisierung des Diagramms nicht erfolgt, da die OnCreate-Methode bereits aufgerufen wird.

Antworten
  • Forum-Beiträge: 11.136

25.08.2014, 23:06:06 via App

Vlt sollte die initialisierung in der OnResume nochmal erfolgen.

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

Antworten
  • Forum-Beiträge: 16

25.08.2014, 23:17:32 via Website

Bringt leider nichts.

Erster Aufruf - Funktioniert
image

Zweiter Aufruf - Klappt nicht

image

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 02:26:25 via App

Ist der Code fürs 2. Aufrufen irgendwie abders als der vom 1.?

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 11:25:14 via Website

Nein, also der Aufruf geschieht ja durch den Main-Activity. Wenn ich die App neu starte und in Main-Activity durch klicken eines Buttons in meine Sub-Activity wechsele dann wird das Diagramm ohne Probleme gezeichnet (siehe Bild 1). Aber wenn ich mit Zurück-Button in Main wechsele und dann wieder durch betätigen von Button in mein Sub-Activity springe wird es nciht mehr gezeichnet (siehe Bild 2).

Hier ist mein Quellcode:

Sub-Activity:

package com.test.testactivity;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Random;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.SeriesSelection;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.tools.PanListener;
import org.achartengine.tools.ZoomEvent;
import org.achartengine.tools.ZoomListener;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Bitmap.CompressFormat;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class ChildActivity_2 extends Activity{

// public static final String TYPE = "type";

private XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();

private XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();

private XYSeries mCurrentSeries;

private XYSeriesRenderer mCurrentRenderer;

private String mDateFormat;


private GraphicalView mChartView;

String tag = "LifeCycleEvents";


static double x = 0;
static double y = 0;

private Update mUpdateTask = new Update();

/*@Override
protected void onRestoreInstanceState(Bundle savedState) {
    super.onRestoreInstanceState(savedState);
    mDataset = (XYMultipleSeriesDataset) savedState.getSerializable("dataset");
    mRenderer = (XYMultipleSeriesRenderer) savedState.getSerializable("renderer");
    mCurrentSeries = (XYSeries) savedState.getSerializable("current_series");
    mCurrentRenderer = (XYSeriesRenderer) savedState.getSerializable("current_renderer");
    mDateFormat = savedState.getString("date_format");

}

@Override
protected void onSaveInstanceState(Bundle outState) {

    super.onSaveInstanceState(outState);
    outState.putSerializable("dataset", mDataset);
    outState.putSerializable("renderer", mRenderer);
    outState.putSerializable("current_series", mCurrentSeries);
    outState.putSerializable("current_renderer", mCurrentRenderer);
    outState.putString("date_format", mDateFormat);
}

*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.child_activity_2);

    initChart();

    mUpdateTask.execute(this);
    Log.d(tag,"In the onCreate() event CHILDACT2");
    }

private void initChart(){

    // Diagrammeigenschaften
            mRenderer.setApplyBackgroundColor(true);
            mRenderer.setBackgroundColor(Color.TRANSPARENT); //Farbe Hintergrund von Diagramm - Transparent
            mRenderer.setAxisTitleTextSize(16);
            mRenderer.setChartTitleTextSize(20);
            mRenderer.setLabelsTextSize(15);
            mRenderer.setLegendTextSize(15);
            mRenderer.setMargins(new int[] { 20, 30, 15, 0 });
            mRenderer.setPointSize(5);
            mRenderer.setXTitle("Time [ s ]");
            mRenderer.setYTitle("Oxygen [ % ]");
            mRenderer.setShowGrid(true);
            mRenderer.setMarginsColor(Color.argb(0x00, 0x01, 0x01, 0x01));  //Farbe menu von Diagramm - Transparent
            mRenderer.setYAxisMin(0);
            mRenderer.setYAxisMax(100);
            mRenderer.setClickEnabled(true);
            mRenderer.setLabelsColor(Color.DKGRAY);
            mRenderer.setGridColor(Color.DKGRAY);
            mRenderer.setAxesColor(Color.DKGRAY);






         //Legende   
            String seriesTitle = "Series " + (mDataset.getSeriesCount() + 1);
            XYSeries series = new XYSeries(seriesTitle);
            mDataset.addSeries(series);
            mCurrentSeries = series;
            XYSeriesRenderer renderer = new XYSeriesRenderer();
            mRenderer.addSeriesRenderer(renderer);
            renderer.setColor(Color.rgb(0,100,0));
            mCurrentRenderer = renderer;

}

@Override
protected void onResume() {
    super.onResume();
    Log.d(tag,"In the onResume() event CHILDACT2");
    initChart();
    if (mChartView == null) {
        LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
        mChartView = ChartFactory.getLineChartView(this, mDataset,mRenderer);

        layout.addView(mChartView, new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));


    } else {
        mChartView.repaint();
    }

}



@Override
protected void onRestart() {
    // TODO Auto-generated method stub
    Log.d(tag,"In the onRestart() event CHILDACT2");
    super.onRestart();
}





@Override
protected void onDestroy() {
    Log.d(tag,"In the onDestroy() event CHILDACT2");
    // TODO Auto-generated method stub
    super.onDestroy();
    finish();
}





@Override
protected void onPause() {
    // TODO Auto-generated method stub
    Log.d(tag,"In the onPause() event CHILDACT2");
    super.onPause();
}

@Override
protected void onStop() {
    // TODO Auto-generated method stub
    Log.d(tag,"In the onStop() event CHILDACT2");
    super.onStop();
}





@Override
protected void onStart() {
    // TODO Auto-generated method stub
    Log.d(tag,"In the onStart() event CHILDACT2");
    super.onStart();

}





protected class Update extends AsyncTask<Context, Integer, String> {
    @Override
    protected String doInBackground(Context... params) {
        MockData random = new MockData();
        int i = 0;
        while (true) {
            try {
                Thread.sleep(1000);
                x = x + 1;
                y = random.myRandom(10, 100);

                publishProgress(i);
                i++;
            } catch (Exception e) {

            }
        }
        // return "COMPLETE!";
    }

    // -- gets called just before thread begins
    @Override
    protected void onPreExecute() {
        super.onPreExecute();

    }


    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        mCurrentSeries.add(x, y);

    //  if (mChartView != null) {
            mChartView.repaint();
    //  }


    }

    // -- called if the cancel button is pressed
    @Override
    protected void onCancelled() {
        super.onCancelled();

    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
            }
}

}

Main -Activity:

package com.test.testactivity;

import android.os.Build;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;

@SuppressLint("NewApi";)
public class MainActivity extends Activity implements OnClickListener {

public ImageButton menueButton_1;
public ImageButton menueButton_2;
public ImageButton menueButton_3;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    menueButton_1 = (ImageButton)findViewById(R.id.menueButton1);
    menueButton_1.setOnClickListener(this);

    menueButton_2 = (ImageButton)findViewById(R.id.menueButton2);
    menueButton_2.setOnClickListener(this);

    menueButton_3 = (ImageButton)findViewById(R.id.menueButton3);
    menueButton_3.setOnClickListener(this);


}

@Override
public void onClick(View v) {

    if(v.getId() == menueButton_1.getId()){

        Intent slideactivity = new Intent(MainActivity.this, ChildActivity_1.class);
        Bundle bndlanimation =  ActivityOptions.makeCustomAnimation(getApplicationContext(), R.anim.animation,R.anim.animation2).toBundle(); 
        startActivity(slideactivity, bndlanimation);

    }
    else if(v.getId() == menueButton_2.getId()){

        Intent slideactivity = new Intent(MainActivity.this, ChildActivity_2.class);
        Bundle bndlanimation =  ActivityOptions.makeCustomAnimation(getApplicationContext(), R.anim.animation,R.anim.animation2).toBundle(); 
        startActivity(slideactivity, bndlanimation);

    }
    else if(v.getId() == menueButton_3.getId()){

        Intent slideactivity = new Intent(MainActivity.this, ChildActivity_3.class);
        Bundle bndlanimation =  ActivityOptions.makeCustomAnimation(getApplicationContext(), R.anim.animation,R.anim.animation2).toBundle(); 
        startActivity(slideactivity, bndlanimation);

    }



}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 11:38:43 via App

Komisch eigentlich sollte das oassen.
Ich nehme an, die 2. Activity wird nur in den Hintergrund gestellt und dann wieder aufgerufen ohne dass sie komplett beendet war.
Hast du das mit dem onResume gemacht?
Sort wieklich alle init zeilen aus der onCreate reingepackt?

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 12:43:17 via Website

Durch den Logs konnte ich sehen, dass die Methode onDestroy() aufgerufen wurde. Dann gehe ich davon aus, dass dieser activate zerstört wird. Hatte zusätzlich die Funktion finish() drin, das hat auch nichts gebracht. Ja ich habe die init auch in onResume reingetan, hat auch nichts gebracht. Ich verstehe wirklich nicht, warum das nicht funktioniert.
Hmm..

Antworten
  • Forum-Beiträge: 1.904

26.08.2014, 13:04:44 via App

Dann pack mal alles in die onResume und guck ob es noch funktioniert.

Wenn dir mein Beitrag gefällt, kannst dich einfach mit dem 👍 "Danke"-Button auf der Website dieses Forums bedanken. 😀

Why Java? - Because I can't C#

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 17:19:45 via App

Und wenn du deine App vollständig beendest und dann nichmal probierst?
Geht es dann?

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 18:12:41 via Website

Ja, dann geht es.. aber nur einmal

— geändert am 26.08.2014, 18:13:12

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 18:23:30 via App

Dann hat es ganz bestimmt etwas mit dem Activity Lifecycle zutn.
Aber warum es nicht tut kann ich nicht sagen.
Gibts irgendwelche Exceptions oder auffälligkeiten im Log?

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 18:33:51 via Website

Ja, diesen hier:

08-26 12:28:20.793: E/SoundPool(286): error loading /system/media/audio/ui/KeypressStandard.ogg

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 18:40:27 via App

Aber ist das direkt aus deiner app oder wird das einfach so angezeigt.
Ist diese Zeile rot gefärbt?

Benutzt du sounds in der App?
Wenn nein ist das kein Fehler deiner App sondern ein Fehler einer anderen App.

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 18:46:19 via Website

Ja sie ist rot gefärbt, ansonsten werden keine andere Exceptions angezeigt. Nein, Sounds benutze ich nicht. Ich habe gemerkt, dass beim zweiten mal die Update Klasse nicht ausgeführt wird. hm.. ich habe versucht sie nach onDestroyed zu killen, hat auch nichts gebracht.

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 19:26:05 via App

Und wenn du das onDestroy löschst?

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 20:56:28 via Website

onDestroy habe ich später hinzugefügt als ich gemerkt habe, dass es nicht funktioniert

Antworten
  • Forum-Beiträge: 1.904

26.08.2014, 21:21:19 via App

Flüchtige Idee: Kann es sein, dass der AsyncTask noch nach onDestroy ausgeführt wird?

Wenn dir mein Beitrag gefällt, kannst dich einfach mit dem 👍 "Danke"-Button auf der Website dieses Forums bedanken. 😀

Why Java? - Because I can't C#

Antworten
  • Forum-Beiträge: 16

26.08.2014, 21:25:44 via Website

Ich habe meine onDestroy Methode geändert.

@Override
protected void onDestroy() {
    Log.d(tag,"In the onDestroy() event CHILDACT2");
    // TODO Auto-generated method stub
    mUpdateTask.cancel(true);
    super.onDestroy();

    finish();
}

So würde ich AsyncTask beenden. Hat aber auch nicht geklappt

Antworten
  • Forum-Beiträge: 16

26.08.2014, 21:50:54 via Website

image

Task Status : Running .. ich werde gleich verrückt

— geändert am 26.08.2014, 22:01:12

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 22:31:34 via App

An dem Task könnte es tatsächlich liegen.

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 22:36:16 via Website

Der wird wie erwartet gestartet und beendet.

Antworten
  • Forum-Beiträge: 16

26.08.2014, 22:41:54 via Website

liegt tatsächlich an dem Task. onProgressUpdate wird nicht nochmal ausgeführt

image

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 22:46:58 via App

Statt das onProgressUpdate zu benutzen könntest du auch context#runOnUiThread benutzen.

Meines wissens sollte es mit deinem Code aber trotzdem laufen..

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

Antworten
  • Forum-Beiträge: 235

26.08.2014, 22:54:14 via Website

Hallo,

Ich habe dein Code NICHT! analysiert. Aus dem, was ich am Anfang gelesen habe, vermute ich einen simplen "repaint- Problem". Sollte ich mich irren - sorry!

In dem "Konstruktor" -> onCreate(.... Methode der Activity wird die:
initChart();
Methode ausgeführt; und danach startet ein mUpdateTask Thread. - OK!

Die "init" bereitet alles was mit der Visualisierung zu tun hat vor, und zeigt alles an.
OK.
Irgend wann (Zurück-Button), .... dein Zweiter Aufruf - Klappt nicht Bild,
werden die Komponente / Neue Werte ... nicht NEUGEZEICHNET!

Das Stichwort heißt: -> repaint.

Was du machen musst, ist lediglich dem Code (Programm- Rumpf) folgen (Breakpoints ... Marker ... setzen) um zu herausfinden, wo du das REPAINT! "aktivieren" muss.
Theoretisch sieht es so aus:
- ....
- Werte Abfragen (Get Value)
- Werte Zeichnen (GUI - Paint Value)
- Werte Abfragen (Get NEW!!! Value)
- Werte neu Zeichnen (REPAINT GUI mit den neuen Werten)
- ...
Wo das bei dir im code alles passiert, .... folge dem Code -> (Breakpoints ... Marker ... setzen!

liegt tatsächlich an dem Task. onProgressUpdate wird nicht nochmal
ausgeführt

Dann soll mit der Fehlerquelle - kein Problem geben.

LG
Georg

Sorry für Gramatik & Stilistik Fehler.

Antworten
  • Forum-Beiträge: 16

26.08.2014, 23:06:03 via Website

Pascal, ja eigentlich müsste es auch so gehen. hm..

Georg, das verstehe ich jetzt nicht so richtig. Der Task startet nicht nochmal. Auch die Methode doInBackground() wird nicht ausgeführt. Das kann nicht an repaint liegen oder?

Antworten
  • Forum-Beiträge: 11.136

26.08.2014, 23:10:08 via App

Vielleicht solltest du deinen AsyncTask ohne static variablem betreiben.
Wozu gibts denn Parameter in Methoden.
Habe aber im Moment keinen Plan woran der Task scheitert

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

Antworten
  • Forum-Beiträge: 16

26.08.2014, 23:42:44 via Website

sieht schlecht aus. Danke trotzdem für deine Mühe!

Antworten
  • Forum-Beiträge: 235

26.08.2014, 23:44:18 via Website

... Der Task startet nicht nochmal ...

ich habe geschrieben, dass ich dein Code nicht Analysiert habe.
Geguckt schon:

...
mUpdateTask.execute(this);
...
protected String doInBackground( { <---- ! Die Methode ist quasi wie Create ... 
...
while (true) { <--- !!! - hier muss schon jehmand (DU?) wissen wass man damit tut!
...

Aber ich mische mich weiter nicht ein. -> sorry.

LG
Georg

Sorry für Gramatik & Stilistik Fehler.

Antworten
  • Forum-Beiträge: 16

27.08.2014, 10:32:30 via Website

Es geht jetzt.
Georg du hattest Recht.
Problem lag an dieser Zeile while (true) {

ich habe es umgeändert auf while(i<20){

und doInBackground return null zugewiesen, dann hat es plötzlich funktioniert.

Danke!!!! :)

Antworten
  • Forum-Beiträge: 1.904

27.08.2014, 20:03:28 via App

Schön!

Wenn dir mein Beitrag gefällt, kannst dich einfach mit dem 👍 "Danke"-Button auf der Website dieses Forums bedanken. 😀

Why Java? - Because I can't C#

Antworten