2015-09-03 11 views
6

Ich habe ein Fragment, das ein Liniendiagramm zeigt, das mit MPAndroidChart erstellt wurde. Das Laden des Fragments dauert ungefähr 200 Millisekunden.Code ausführen, nachdem ein Fragment zum ersten Mal sichtbar wird

Ich möchte die wahrgenommene App-Leistung verbessern, indem ich die Diagrammdaten unmittelbar nachdem das Fragment sichtbar wird geladen habe.

Daher muss ich Code direkt nachdem das Fragment sichtbar wird, aber nur zum ersten Mal wird es sichtbar.

Ich kann onResume() nicht verwenden, da es aufgerufen wird, bevor das Fragment sichtbar ist.

Hinweis: Ich kann keine asynchrone Aufgabe verwenden, sie muss auf dem UI-Thread ausgeführt werden. Es würde sowieso keinen Sinn ergeben, da dies eine einmalige Initialisierung ist, die nur etwa 200 Millisekunden dauert.

+0

Sie sagen, Sie können den Code nicht in das 'onResume' des Fragments oder das' onResume' der Aktivität einfügen? – ChrisStillwell

+0

Derzeit befindet sich der Code im onCreateView() des Fragments. Ich kann onResume() sowieso nicht verwenden, weder die Aktivität noch das onResume() des Fragments. – Mike76

+0

Ich bin mir nicht sicher, ob ich verstehe, warum Sie das 'onResume' des Fragments nicht verwenden können. Diese Methode wird aufgerufen, nachdem das Fragment sichtbar wird. – ChrisStillwell

Antwort

0

Setzen Sie es in die onViewCreated() -Methode.

+2

Scheint das Falsche zu sein. Es wird noch vor onResume() aufgerufen. -> ...... "Wird unmittelbar nach dem Aufruf von onCreateView (LayoutInflater, ViewGroup, Bundle) aufgerufen, aber bevor ein gespeicherter Status in der Ansicht wiederhergestellt wurde. Die Ansichtshierarchie des Fragments ist jedoch zu diesem Zeitpunkt noch nicht mit dem übergeordneten Element verknüpft . " – Mike76

1

Das langwierige Ausführen von UI-Threads ist eine schlechte Übung - Sie blockieren die gesamte Benutzeroberfläche für die Dauer Ihrer Verarbeitung (da es nur einen UI-Thread gibt). Und 200ms ist eigentlich sehr lang, es ist 1/5 Sekunde, leicht vom menschlichen Auge zu erkennen, stellen Sie sich vor, Sie spielen ein Spiel mit einer Bildrate von 5 Bildern pro Sekunde.

Bei der wahrgenommenen Leistung geht es nie darum, UI-Verzögerungen zu haben.

Verwenden Sie entweder AsyncTask oder AsyncTaskLoader, um Ihre Daten zu verarbeiten, Callbacks werden auf dem UI-Thread aufgerufen, also keine Sorgen. Sie können steuern, ob es einmalig ist oder nicht, indem Sie die Daten beispielsweise in einer Mitgliedsvariablen speichern. Wenn es null ist - laden, wenn nicht - sofort verwenden.

Wenn Ihre Daten relativ statisch und nicht sehr groß sind - laden Sie sie vor dem Öffnen Ihres Fragments (z. B. beim Start der Aktivität oder sogar beim Start der App) und übergeben Sie die Daten nur beim Antasten an das Fragment (über ein Bundle Argument).

+0

Ich kann AsyncTask nicht verwenden, da ich mein Diagramm im UI-Thread initialisieren muss. 200 Millisekunden sind lang, aber der Benutzer kann nichts ohne dieses Diagramm tun. Daher kann ich nur einen Fortschrittsbalken für die 200 Millisekunden anzeigen. – Mike76

+0

Ihr Fortschrittsbalken wird eingefroren, wenn Sie 200ms der UI-Thread-Zeit nehmen. Warum muss sie im UI-Thread verarbeitet werden? –

+0

Das stimmt, aber bei der Verarbeitung geht es nur darum, die Benutzeroberfläche des Diagramms zu aktualisieren. – Mike76

6
public class MyFragment extends Fragment{ 
    Boolean _areLecturesLoaded =false; 
    @Override 
    onCreateView(){ 
    //Inflate the required views. Code gets executed once View is made but not shown 
    return v; 
} 
@Override 
    public void setUserVisibleHint(boolean isVisibleToUser) { 
     super.setUserVisibleHint(isVisibleToUser); 
     //Code executes EVERY TIME user views the fragment 

     if (isVisibleToUser && !_areLecturesLoaded) { 
      _areLecturesLoaded = true; 
      // Code executes ONLY THE FIRST TIME fragment is viewed. 
     } 
    } 
} 

isVisisbleToUser ist integriert und es ist wahr, wenn der Benutzer das aktuelle Fragment sehen. Bis der Benutzer das Fragment zum ersten Mal sieht, bleibt es falsch. Wenn Sie möchten, dass Code ausgeführt wird, wenn der Benutzer das Fragment anzeigt, platzieren Sie den Code in diesem Bereich, aber außerhalb der if-Anweisung.

_areLecturesLoaded als falsch und einmal das Fragment zum ersten Mal initialisiert wird, wird es auf true gesetzt die If-Anweisung sichergestellt wird in Zukunft nicht mehr aufgerufen werden und der Code innerhalb ausgeführt wird nur einmal

Alle Initialisierung von Ansichten Widgets-Buttons usw. müssen in onCreate() ausgeführt werden, um die Möglichkeit eines Null-Pointers und anderer lästiger Ausnahmen zu vermeiden.

+0

Danke, ich werde es versuchen. – Mike76

+0

lassen Sie mich wissen, wenn Sie irgendwelche Probleme haben. Sonst akzeptiere die Antwort. Danke –

+0

Leider empfängt setUserVisibleHint nie einen Anruf. Ich habe es mit Protokollen auf Android 4.4 getestet. Vielleicht funktioniert es nur, wenn ich einen Viewpager oder sowas benutzen würde. – Mike76

0

Es kann mithilfe einer statischen booleschen Variablen implementiert werden. Ich habe den folgenden Code verwendet, um den Fortschrittsdialog nur beim ersten Start der App anzuzeigen.

public class SettingsFragment extends Fragment { 

    static boolean _areLecturesLoaded = true; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragment_settings, container, false); 

     return rootView; 
    } 

    private class Getlimits extends AsyncTask<Void, Void, Void> { 
     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      pd = ProgressDialog.show(getActivity(), "", "Loading...", true); 
      pd.setCancelable(false); 
     } 

     @Override 
     protected Void doInBackground(Void... arg0) { 
      //your background code 
      if(_areLecturesLoaded) { 
       try { 
        Thread.sleep(3500); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 

      return null; 
     } 
     @Override 
     protected void onPostExecute(Void result) { 
      super.onPostExecute(result); 
      // Dismiss the progress dialog 
      if (pd.isShowing()) 
       pd.dismiss(); 
      _areLecturesLoaded = false; 
     } 
    } 
} 
Verwandte Themen