ListViewに大量のデータがセットされた状態でスクロールすると画面が強制終了してしまう

1,577 views
Skip to first unread message

ryoryo

unread,
Sep 17, 2010, 6:51:57 AM9/17/10
to 日本Androidの会
こんにちわ。ryoryoと申します。

現在辞書アプリを開発しており、表題の件ではまっております。

具体的に申しますと、ListViewに表示している検索結果が大量にある場合、
スクロールしていくと大体200行を超えたあたりでいきなり画面が閉じ、
前の画面が表示されます。画面が“閉じた”というか“落ちた”という感じです。

検索用に用意した語句は約45,000語あります。
いずれは検索結果を20件ずつ表示しListViewのaddFooterViewで配置するボタンで、続きの
20件を追加していく用に表示させたいと考えており、ひとまず大量の検索結果が出た場合、
最後まで表示されるかをチェックしたところ、今回の現象を確認した次第です。

検索結果画面に使用しているソースを簡素化した形ですが記載させて頂きます。
(ListViewに表示する内容も簡素化していますが、実際は1行に語句名以外にも種別名
や例文などいろいろ表示しています。※画像は表示していません。)

メモリの枯渇が原因か?とは思ったのですが、原因および解決方法が未だにわからない
状態です。
そもそもListViewにこんなにデータを表示させるものではないのでしょうか?

Android開発がまだ不慣れなため、説明不足や分かりずらい点などあるかと思いますが、
何卒、ご教授の程よろしくお願い致します。

■当方の開発環境
 開発用PCのOS:Windows 7 Enterprise
 開発プラットフォーム:Eclipse 3.5.2
 アンドロイドOS:1.6以上
 アプリ実行環境:Xperia(実機), Xperia(emulator), Android Virtual Devices

以下ソースです。
-
START--------------------------------------------------------------------------
【dictionaryresults.xml】
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView
android:id="@+id/lstResults"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF"
android:cacheColorHint="#FFFFFF"
/>
</LinearLayout>

【dictionaryresultslist.xml(各行に使用しているxml)】
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/
android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/wordLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/wordName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/theme_color"
android:textSize="24sp"
/>
<TextView
android:id="@+id/wordCode"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="0dp"
/>
</LinearLayout>
</RelativeLayout>

【DictionaryResultsController.java】
public class DictionaryResultsController extends Activity{
private ArrayList<DictionaryResultsListProperty> _ArrayList;
private DictionaryResultsListAdapter
_DictionaryResultsListAdapter;
private ListView _LstResults;

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

private void ViewData(){
_LstResults = (ListView)findViewById(R.id.lstResults);
_ArrayList = new ArrayList<DictionaryResultsListProperty>();
SQLiteCursor cursor = GetHogeHoge(); // ←ここでデータベースから検索結果を取得
int resultNum = cursor.getCount();
cursor.moveToFirst();

DictionaryResultsListProperty dictionaryResultsListProperty;
for(int i=0; i <= maxCount; i++){
/*****************
/* ここでDictionaryResultsListPropertyに検索結果の値を入れる
/*****************
dictionaryResultsListProperty = new
DictionaryResultsListProperty();
dictionaryResultsListProperty.SetWordCode(cursor.getString(0));
dictionaryResultsListProperty.SetWordName(cursor.getString(1));
dictionaryResultsListProperty.SetKindCode(cursor.getString(2));
_ArrayList.add(dictionaryResultsListProperty);
cursor.moveToNext();
}
_DictionaryResultsListAdapter = new
DictionaryResultsListAdapter(this, R.layout.dictionaryresultslist,
_ArrayList);
_LstResults.setAdapter(_DictionaryResultsListAdapter);
}
}

【DictionaryResultsListProperty.java】
public class DictionaryResultsListProperty{
private String _WordCode;
private String _WordName;
private String _KindCode;

public void SetWordCode(String value){
this._WordCode = value;
}
public void SetWordName(String value){
this._WordName = value;
}
public void SetKindCode(String value){
this._KindCode = value;
}

public String GetWordCode(){
return this._WordCode;
}
public String GetWordName(){
return this._WordName;
}
public String GetKindCode(){
return this._KindCode;
}
}


【DictionaryResultsListAdapter.java】
public class DictionaryResultsListAdapter extends
ArrayAdapter<Object>{
private ArrayList<?> items;
private LayoutInflater inflater;

public DictionaryResultsListAdapter(Context context, int
textViewResourceId, ArrayList items){
super(context, textViewResourceId, items);
this.items = items;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

static class ViewHolder{
LinearLayout wordLayout;
TextView wordCode;
TextView wordName;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
// ビューを受け取る
View view = convertView;
ViewHolder holder;

if (view == null){
view = inflater.inflate(R.layout.dictionaryresultslist, null);
holder = new ViewHolder();
holder.wordLayout =
(LinearLayout)view.findViewById(R.id.wordLayout);
holder.wordCode = (TextView) view.findViewById(R.id.wordCode);
holder.wordName = (TextView) view.findViewById(R.id.wordName);
view.setTag(holder);
}else{
holder = (ViewHolder)view.getTag();
}

// 表示すべきデータの取得
DictionaryResultsListProperty item =
(DictionaryResultsListProperty)items.get(position);
if (item != null){
String kindCode = item.GetKindCode();
holder.wordCode.setText(item.GetWordCode());
holder.wordName.setText(item.GetWordName());
if(kindCode.equals(ConstDefine.KIND_COLOR)){

holder.wordLayout.setBackgroundColor(Color.parseColor(item.GetColorValue()));
}else{
holder.wordLayout.setBackgroundColor(Color.argb(0, 255, 255,
255));
}
}
return view;
}
}
-
END----------------------------------------------------------------------------

Rabbit-U

unread,
Sep 17, 2010, 8:01:47 AM9/17/10
to 日本Androidの会
Rabbit-Uです。

AndroidManifest.xml の debuggable を true にするとか、
LogCat を見ると何か書いてあるかもしれません。

HIGAKI Kenji

unread,
Sep 17, 2010, 8:25:26 AM9/17/10
to android-g...@googlegroups.com
higaki と申します。

データベースの検索結果を Cursor 経由で表示するのであれば、
ArrayAdapter ではなく、SimpleCursorAdapter を使うか、
CursorAdapter を継承して使うのがよいのではないでしょうか。
そうすれば、

1. Cursor を渡して Adapter を生成する。
2. Adapter を ListView に setAdapter する。

だけで済むと思います。
あ、あと startManagingCursor() しておけば、Cursor のあとしまつも
してくれます。

mosaki4

unread,
Sep 20, 2010, 3:36:06 AM9/20/10
to android-g...@googlegroups.com
大崎といいます

higaki さんが解説されていた方法(SimpleCursorAdapter)で試してみたところ
1000件でも表示ができました

ただこれを実機でスクロールさせてみたところ
内容を閲覧できないような速さで高速に最下部までスクロールさせても
1000件で2,30秒はかかります
(内容を閲覧しながらだと数分以上はかかる?)

上記の点を考えるとあまり多量のデータを表示させても
ユーザーが全てを閲覧するのは困難かもしれません
下記のような方法はどうでしょうか?
設定画面でユーザーが選択可能にしておくのもいいかもしれません。

1.検索結果は全て表示する
2.検索結果がある程度以上の場合は、確認ダイアログを表示
3.検索結果がある程度以下の条件になるまで表示しない
4.検索結果をある程度を上限として表示、それ以上は表示しない


2010年9月17日19:51 ryoryo <ryo...@livedoor.com>:

--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。


ryoryo

unread,
Sep 25, 2010, 12:30:23 PM9/25/10
to 日本Androidの会
こんばんわ、ryoryoです。

返信が遅くなってしまい大変申し訳ありません。

Rabbit-U様、ご返信頂きましてありがとうございます。
LogCatでの確認はしていませんでしたが、debuggable を true にし、
Eclipseではログの確認をしていましたが、特に気になるログは見つけ
られませんでした。
(※見落としているかも知れません。。。)

higaki様、ご返信頂きましてありがとうございます。
SimpleCursorAdapterでの方法を試してみたいと思います。
また、startManagingCursor() の件もありがとうございます!!
そんな便利なものがあるとは知りませんでした。。。
勉強になります!

大崎様、ご返信頂きましてありがとうございます。
SimpleCursorAdapterの件、試して頂きありがとうございます!
確かに検索結果が大量にある場合、全てユーザに確認させるとしたら
かなり時間がかかってしまいますね。。。

>設定画面でユーザーが選択可能にしておくのもいいかもしれません。
上記に関しては、検討したいと思います。
貴重なご提案をありがとうございます!!!

皆様ご教授頂きましてありがとうございます!
まずはご教授頂きました方法を組み込んでみたいと思います!

On 9月20日, 午後4:36, mosaki4 <mosa...@gmail.com> wrote:
> 大崎といいます
>
> higaki さんが解説されていた方法(SimpleCursorAdapter)で試してみたところ
> 1000件でも表示ができました
>
> ただこれを実機でスクロールさせてみたところ
> 内容を閲覧できないような速さで高速に最下部までスクロールさせても
> 1000件で2,30秒はかかります
> (内容を閲覧しながらだと数分以上はかかる?)
>
> 上記の点を考えるとあまり多量のデータを表示させても
> ユーザーが全てを閲覧するのは困難かもしれません
> 下記のような方法はどうでしょうか?
> 設定画面でユーザーが選択可能にしておくのもいいかもしれません。
>
> 1.検索結果は全て表示する
> 2.検索結果がある程度以上の場合は、確認ダイアログを表示
> 3.検索結果がある程度以下の条件になるまで表示しない
> 4.検索結果をある程度を上限として表示、それ以上は表示しない
>
> 2010年9月17日19:51 ryoryo <ryo_...@livedoor.com>:
> ...
>
> もっと読む ≫
Reply all
Reply to author
Forward
0 new messages