В моей работе есть настраиваемая строка заголовка и ListView. ListView использует SimpleAdapter, показывающий массив данных, ничего необычного. Я заметил, что, когда я продолжаю скользить пальцем вверх и вниз, не выходя из экрана, довольно часто прокрутка останавливается, и полоса прокрутки исчезает. Это никогда не происходит в активности почтовых ящиков Gmail. В приложении NPR News активность в меню имеет такую же проблему. Что я пропустил?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/title_bar"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.WindowTitle">
<Button
android:id="@+id/accounts_filter"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
style="@android:style/Widget.Button.Small"
android:maxWidth="200sp"
android:singleLine="true"
android:ellipsize="marquee"
android:onClick="openFilter"/>
</RelativeLayout>
<ListView android:id="@+id/accounts_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
Мне было любопытно, поэтому я установил приложение новостей NPR и получил возможность реплицировать вашу ошибку.
Из того, что я понимаю, они кэшируют Bitmaps из Интернета в своем адаптере, и он зависает всякий раз, когда кешу нужно снова загружать эти растровые изображения (по какой-либо причине). Дело в том, что при непрерывных событиях прокрутки вы должны прокручивать сразу несколько элементов списка, поэтому, если одному элементу необходимо обновить его кешированное значение, есть хороший шанс, что другие предметы тоже нуждаются в нем. В зависимости от реализации адаптера может произойти какая-то странная параллельная модификация.
здесь прослеживается то, что происходит, когда он висит: адаптер становится все более запутанным.
05-21 08:53:07.570: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/machoman_sq.jpg?t=1305913905&s=12
05-21 08:53:07.580: DEBUG/org.npr.android.util.PlaylistProvider(6457): content://org.npr.android.util.Playlist;story_id = ?;[136497574]
05-21 08:53:07.580: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/pelosi_flex.jpg?t=1305924952&s=12
05-21 08:53:07.610: DEBUG/org.npr.android.news.DownloadDrawable(6457): Got bitmap
05-21 08:53:07.610: DEBUG/org.npr.android.news.DownloadDrawable(6457): Download complete
05-21 08:53:07.610: DEBUG/org.npr.android.news.DownloadDrawable(6457): Starting download
05-21 08:53:07.620: DEBUG/org.npr.android.util.PlaylistProvider(6457): content://org.npr.android.util.Playlist;story_id = ?;[136507004]
05-21 08:53:07.620: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/capitol.jpg?t=1305929989&s=12
05-21 08:53:07.630: DEBUG/org.npr.android.util.PlaylistProvider(6457): content://org.npr.android.util.Playlist;story_id = ?;[136498068]
05-21 08:53:07.630: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/ppw1.jpg?t=1305913144&s=12
05-21 08:53:07.640: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/levee.jpg?t=1305901869&s=12
05-21 08:53:07.670: WARN/org.npr.android.news.NewsListAdapter(6457): Could not find list item at position 27
05-21 08:53:07.680: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/imf.jpg?t=1305915244&s=12
05-21 08:53:07.710: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/syria.jpg?t=1305904814&s=12
05-21 08:53:07.750: DEBUG/org.npr.android.news.ImageThreadLoader(6457): Cache hit: http://media.npr.org/assets/img/2011/05/20/netanyahu.jpg?t=1305900960&s=12
05-21 08:53:07.850: DEBUG/org.npr.android.news.DownloadDrawable(6457): Got bitmap
05-21 08:53:07.850: DEBUG/org.npr.android.news.DownloadDrawable(6457): Download complete
05-21 08:53:07.860: DEBUG/org.npr.android.news.DownloadDrawable(6457): Starting download
05-21 08:53:07.880: WARN/org.npr.android.news.NewsListAdapter(6457): Could not find list item at position 28
05-21 08:53:08.510: DEBUG/org.npr.android.news.DownloadDrawable(6457): Got bitmap
05-21 08:53:08.510: DEBUG/org.npr.android.news.DownloadDrawable(6457): Download complete
05-21 08:53:08.550: WARN/org.npr.android.news.NewsListAdapter(6457): Could not find list item at position 29
Мое предложение: использовать заполнители? Извлеките адаптер из кеша, извлеките местозаполнитель, когда он не найден, и вызовите операцию фонового потока, когда кеш недействителен.
Попробуйте использовать DroidDraw для всех проблем с компоновкой. Его приложение для перетаскивания рабочего стола для создания макетов Android. Я всегда использую его всякий раз, когда я придерживаюсь макетов. И я думаю, вы должны использовать Tablelayout
в своем макете и поставить кнопку и перечислить в Tablerow
.
Вот образец макета, который я создал для своего приложения с одной кнопкой и списком
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/apps"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="@+id/undoApps"
android:layout_height="60dip"
android:layout_width="320dip"
android:text="I AM A BUTTON"
android:textSize="22sp"
android:textStyle="bold"
android:typeface="serif">
</Button>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@android:id/list"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:drawSelectorOnTop="false" >
</ListView>
</TableRow>
</TableLayout>