私はAndroidプログラミングの初心者です。ListViewとArrayAdapterをいくつか調べた後、練習用の簡単なデモプログラムを作成することにしました。
カスタムビュースタイルのListViewを表示したいので、ArrayAdapterのgetView()関数をオーバーライドします。メモリリークを防ぐために、パラメータconvertViewをチェックし、convertViewがnullの場合にのみ新しいオブジェクトを拡張する必要があることを知っています。また、AsyncTaskを作成して、バックグラウンド(doInBackground内)でArrayAdapterにデータを追加し続け、notifyDataChangedをListView(onProgressUpdate()内)に保持します。
問題は次のとおりです。MAX_ITEM=50(つまり、AsyncTaskに追加するデータの数)を設定すると、すべてが正常に機能します。しかし、MAX_ITEM = 500を設定すると、logcatは次のエラーメッセージを表示します:「原因:android.view.ViewRootImpl $ CalledFromWrongThreadException:ビュー階層を作成した元のスレッドのみがビューにアクセスできます。」アプリケーションがシャットダウンしました。誰かが問題がどこにあるか教えてもらえますか?以下は私のソースコード「MyTest.java」と私のレイアウトxmlファイル「main.xml」と「layout_row.xml」です。ご覧いただきありがとうございます。
MyTest.Java:
public class MyTest extends Activity {
private static final String TAG="Tany";
private static final int MAX_ITEM = 50;
private MyArrayAdapter adapter;
private ListView listview;
private int addCounter = 0;
public class MyData implements Comparable<MyData>{
public String str1;
public String str2;
public String str3;
public MyData(String str1, String str2, String str3){
this.str1 = str1;
this.str2 = str2;
this.str3 = str3;
}
@Override
public int compareTo(MyData data) {
// TODO Auto-generated method stub
int result = this.str1.compareTo(data.str1);
return result;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listview = (ListView)findViewById(R.id.listview);
adapter = new MyArrayAdapter(this, R.layout.layout_row);
//set adapter
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
Log.d(TAG, "position "+position+" is clicked");
Toast.makeText(parent.getContext(), adapter.getItem(position).str1+", "+adapter.getItem(position).str2, Toast.LENGTH_SHORT).show();
}
});
listview.setTextFilterEnabled(true);
}
public void onStart(){
super.onStart();
MyTask newTask = new MyTask();
newTask.execute();
}
public class MyTask extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
for(int i = addCounter; i<MAX_ITEM; i++)
{
adapter.add(new MyData("str1="+i,"str2="+i,"str3="+i));
addCounter++;
publishProgress();
}
return null;
}
@Override
protected void onProgressUpdate(Void... progress ){
adapter.notifyDataSetChanged();
}
@Override
protected void onPostExecute(Void result){
Log.d(TAG, "AsyncTask MyTask finsish its work");
}
}
public class MyArrayAdapter extends ArrayAdapter<MyData>{
public MyArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
// TODO Auto-generated constructor stub
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if(convertView == null){
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.layout_row, parent, false);
}else{
Log.d(TAG,"recycle view, pos="+position);
row = convertView;
}
TextView tv1 = (TextView) row.findViewById(R.id.textView1);
tv1.setText( ((MyData)getItem(position)).str1 );
TextView tv2 = (TextView) row.findViewById(R.id.textView2);
tv2.setText( ((MyData)getItem(position)).str2 );
TextView tv3 = (TextView) row.findViewById(R.id.textView3);
tv3.setText( ((MyData)getItem(position)).str3 );
return row;
}
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/vertical_container"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="@string/list_title_start"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TextView>
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ListView>
<TextView
android:text="@string/list_title_end"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
layout_row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/linearLayout1"
android:orientation="horizontal">
<ImageView
android:layout_height="wrap_content"
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:src="@drawable/ic_launcher">
</ImageView>
<TextView
android:text="TextView1"
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceLarge">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/linearLayout1"
android:orientation="horizontal">
<TextView
android:id="@+id/textView2"
android:text="TextView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall">
</TextView>
<TextView
android:text="TextView"
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_marginLeft="6dip">
</TextView>
</LinearLayout>
</LinearLayout>