2012-06-11 11 views
6

Ich habe eine ViewPager und eine GridView, um einen monatlichen Kalender anzuzeigen. Die GridView hat etwa 30 Elemente und Swipe nach links und rechts ist sehr langsam. Ich habe ein Beispielprojekt zum Testen ohne Datenbankzugriff erstellt und es ist auch langsam. Vielleicht sieht jemand das Problem oder muss ich die Seiten asynchron laden?Warum sind ViewPager und GridLayout mit 30 Elementen sehr langsam?

Das ist das Layout für ein Element in der GridView. Ich möchte 9 kleine 5x5 Pixel Icons in jedem Element zeigen, aber ohne sie ist es auch langsam.

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/Layout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:padding="1dp"> 
    <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> 
    <TextView android:id="@+id/date" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginLeft="5dp" android:gravity="center_vertical" android:textSize="14sp" android:textStyle="bold"/> 
    </LinearLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot1" android:layout_width="wrap_content" android:drawingCacheQuality="auto" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:background="#ffffff" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:paddingBottom="1dp" android:paddingLeft="1dp" android:paddingTop="5dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_gravity="right" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_gravity="center_horizontal" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_gravity="left" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_gravity="left" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_gravity="left" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_gravity="left" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="#ffffff" android:paddingBottom="1dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> 
    <ImageView android:id="@+id/dot9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_gravity="left" android:background="#ffffff" android:paddingBottom="5dp" android:paddingLeft="1dp"/> 
    </RelativeLayout> 
</LinearLayout> 

Das ist die instantiateItem von GridView Adapter ist:

public Object instantiateItem(ViewGroup container, int position) { 
    GridView gv = new GridView(m_context); 
    gv.setAdapter(new BaseAdapter() { 
     @Override 
     public View getView(int pos, View convertView, ViewGroup parent) { 
      View v; 
      if (convertView == null) { 
       // if it's not recycled, initialize some attributes 
       v = mInflater.inflate(R.layout.calendar_month_item, null); 
      } else { 
       v = convertView; 
      } 
      TextView dayView = (TextView) v.findViewById(R.id.date); 
      dayView.setText(pos + ""); 
      return v; 
     } 

     @Override 
     public long getItemId(int p) { 
      return 0; 
     } 

     @Override 
     public Object getItem(int p) { 
      return null; 
     } 

     @Override 
     public int getCount() { 
      return 30; 
     } 
    }); 
    gv.setNumColumns(5); 
    ((ViewPager) container).addView(gv); 
    return gv; 
} 
+4

Verwenden Sie TraceView, um festzustellen, wo Ihre Engpässe liegen. – CommonsWare

+0

Ich schaute in TraceView, aber ich kann nicht sehen, wo das Problem ist, seine einzige UI-Darstellung. – MOST2K2

+2

Sie wickeln Sie ImageViews in RelativeLayouts und Ihr TextView in einem LinearLayout ein: Das ist völlig unnötig. Zweitens haben Sie mehrere GridViews ... Haben Sie mehrere Adapter? Sie brauchen nicht alle Adapter. Sie können alles in einem Adapter verwalten! Zum Schluss, wenn Sie darüber nachdenken, brauchen Sie keinen ViewPager. Mit einfachen Animationen können Sie dies mit einem einzigen GridView (und einem einzelnen Adapter jedes Mal zurückgesetzt) ​​arbeiten lassen. Viel Glück –

Antwort

5

Ich sah mich um für ein bisschen und ich denke, ich fand genau das, was Sie suchen,:

  • content XML, werden Sie wahrscheinlich Ihr Layout ändern oder zu wiederholen, wie es stellt sich heraus, ziemlich groß ist, wie Sie sagte.
  • CalendarAdapter.java, in Zeile 112 können Sie sehen, dass sie dort ein Symbol hinzugefügt haben. Ändern Sie einfach den Code, damit Sie Ihre neun Symbole programmatisch hinzufügen können, anstatt alle diese Layouts zu haben.
  • How to implement CalendarView in Android
+0

Ja, ich kenne dieses Projekt. aber ich brauche 9 Symbole (und sie haben aktiviert/deaktiviert Zustand) in einem Element der Gridview, also füge ich sie programmatisch im Moment. Vielleicht lege ich sie in das Layout und zeige die benötigten auf und verstecke die anderen. Ich werde erneut posten, wenn das den Viewpager mit der Gridview beschleunigt. – MOST2K2

+0

Ich habe mir das nochmal angesehen und ich denke du solltest bei dem bleiben was ich vorher gesagt habe. Anstatt alle diese Symbole in der "Monatsansicht" des Kalenders anzuzeigen, sollten Sie nur ein Symbol anzeigen, wenn dieser Tag Symbole enthält. Wenn Sie dann den Tag in der "Monatsansicht" auswählen, wird ein Dialogfeld dieses Tages angezeigt, das alle Symbole enthält, die der Benutzer an diesem Tag hinzugefügt hat. Es ist einfacher zu reinigen und arbeitet viel schneller. Sie können auch versuchen, eine SQLite-Datenbank zu verwenden, um alle Tage mit Symbolen und den darin enthaltenen Symbolen zu speichern. Sie haben dann viele Optionen wie eine "To-do-Liste" oder was auch immer. – CommonKnowledge

+0

@ MOST2K2 In dem, was ich oben beschrieben habe, können Sie einen benutzerdefinierten Dialog verwenden und er wird seine eigene XML-Datei haben. – CommonKnowledge

2

Welche Version von Android verwenden Sie? Das ist wichtig, weil es in Android 3.0 einen Kalender gibt, der Bugs hat, aber nicht so kritisch.

Über Ihre Frage, wenn ich es gut verstanden habe. Sehen Sie sich Ihr XML an, es enthält 11 Layouts, und dies ist nur für ein Element. Wenn Sie viele haben, stellen Sie sich vor, wie viel Arbeit das Android-System leisten muss, um all Ihre Elemente aufzublasen. Wenn Sie danach streichen, verwenden Sie die Elemente erneut und Android muss die ungültigen Elemente aktualisieren. Das ist eine Menge Arbeit. (11 Layouts * 30 = 330 Layouts, die aktualisiert oder aufgebläht werden sollen). Wie in der Dokumentation des Android-Entwicklers angegeben, müssen Sie immer so wenige Layouts verwenden, wie möglich, um Ihre Elemente zu umhüllen!

Wie auch immer, Ihr Ansatz ist nicht korrekt. Ich kann Ihnen vorschlagen, sich den Quellcode des CalendarView in Android 3+ anzusehen, aber um Ihnen einen Hinweis zu geben:

Erstellen Sie ein Layout für eine Woche, nicht für jeden Tag (wie in CalendarView). Auf diese Weise muss Android nur n Elemente aktualisieren (Sie wählen aus, wie viele Wochen Sie zu einem bestimmten Zeitpunkt anzeigen möchten), nicht 30. Dieses Layout muss für jeden Tag 7 Ansichten enthalten.

Hoffe, Sie bekommen eine Idee von diesem.

+0

Ich benutze Android 4.0.4 bei meinem Samsung Galaxy Nexus. aber ich möchte meine app für api level> 8 (2.2.x), ich benutze nicht den internen kalender, es ist meine eigene implementierung. Ja, das stimmt, 330 Layouts sind eine Menge Arbeit, und das ist für jeden Monat. Ich habe auch eine Wochen- und Tagesperspektive. Diese sind sehr schnell, wenn Sie nach links oder rechts wischen. Ich versuche, die Layouts zu reduzieren und ich hoffe, dass es funktioniert. vielleicht wechsle ich zu fragmenten und führe eine antsynchrone ladung der seiten aus. – MOST2K2

+0

Warum etwas erfinden, wenn es bereits einen Kalender gibt? Zum Beispiel musste ich einige Kreise in jede Zeile des Android-Kalenders zeichnen. Ich habe den Quellcode dieses Kalenders heruntergeladen und einige Zeilen geändert, und es funktioniert. Ich habe es nicht auf 2.2 getestet, nur 3+. – XMight

+0

Ich benutze meinen Kalender für ein Klassenbuch für Lehrer, es ist sehr spezifisch mit nur 1-10 Stunden. – MOST2K2

0

Zunächst einmal ist Ihr Layout ein wenig seltsam, wie von anderen erwähnt.

  • Sie benötigen das Schema für Layout-Unterelemente wirklich nicht.
  • Mehrere verschachtelte relative oder lineare Layouts, wenn sie nicht benötigt werden, sind ziemlich teuer, besonders wenn sie in ein GridView eingebettet in einem ViewPager eingebettet sind.
  • Zweitens sind der ViewPager und PagerAdapter ein bisschen schwierig.

  • Wenn Sie die Standardanzahl von Offscreen-Seiten haben, werden Sie alle drei gleichzeitig anzeigen. Wenn Sie es höher setzen, werden Sie noch mehr Ansichten layout.
  • Stellen Sie sicher, dass Sie Ansichten in destroyItem korrekt entfernen.
  • Implementieren Sie die isViewFromObject Methode korrekt, da andernfalls Ihre Ansichten verworfen werden, wenn Sie die Seite aufrufen, was zu höheren Kosten für die Neuerstellung führt.

Mit @ CommonsWare Ratschläge gehen ist wahrscheinlich eine gute Idee. TraceView ist ein bisschen schwierig zu benutzen, aber es wird wahrscheinlich einige Hinweise geben.

+0

Ja das ist wahr, dass ich solche Unterelemente nicht brauche. Ich ändere nicht die Standard Offscreen-Seiten von 3. entfernen und isViewFromObject ist korrekt implementiert. – MOST2K2