質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

1184閲覧

Androidアプリ開発[Java] ListViewのカスタマイズでBaseAdapterで値を保持するためのViewHolderといったクラスは必要なのか。

gugupoo

総合スコア31

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2021/06/07 06:34

ネット上で見つけて利用させて頂いている
https://akira-watson.com/android/baseadapter.html より
BaseAdapterを継承したTestAdapterというものがあります。

import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class TestAdapter extends BaseAdapter { private LayoutInflater inflater; private int layoutID; private String[] namelist; private String[] emaillist; private Bitmap[] photolist; static class ViewHolder { //今回質問question ここのclassを外すことはできないのか。 TextView text; TextView email; ImageView img; } TestAdapter(Context context, int itemLayoutId, String[] names, String[] emails, int[] photos ){ inflater = LayoutInflater.from(context); layoutID = itemLayoutId; namelist = names; emaillist = emails; // bitmapの配列 photolist = new Bitmap[photos.length]; // drawableのIDからbitmapに変換 for( int i = 0; i< photos.length; i++){ photolist[i] = BitmapFactory.decodeResource(context.getResources(), photos[i]); } } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(layoutID, null); holder = new ViewHolder(); holder.img = convertView.findViewById(R.id.img_item); holder.text = convertView.findViewById(R.id.text_view); holder.email = convertView.findViewById(R.id.text_mail); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.img.setImageBitmap(photolist[position]); String str = "Staff ID.170900"+ String.valueOf(position+1) + "\n\nEmail: " + emaillist[position] + "\nTel: 020-8931-9933 #340" + String.valueOf(position+1); holder.email.setText(str); holder.text.setText(namelist[position]); return convertView; } @Override public int getCount() { return namelist.length; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } }

以上は正常に動くサンプルですが、
自分の中で疑問が起きまして、
値を保持するための ViewHolderクラスというものに目がいきまして、

static class ViewHolder {
TextView text;
TextView email;
ImageView img;
}

確かにこれで値は保持されるのかもしれませんが、
このViewHolder というクラスを作成して
その中に
TextView text;
TextView email;
ImageView img;

というものを作成してやる必要があるのか疑問に思えました。
getViewメソッド以下に 
ViewHolder holder;
として、
holder.img = convertView.findViewById(R.id.img_item);  とか
holder.text = convertView.findViewById(R.id.text_view); という形でなく、

ViewHolder holder; とわざわざしなくて
TextView text;
TextView email;
ImageView img;
これらをもとに
もっとダイレクトに記載できないものかと。
text = convertView.findViewById(R.id.text_view);

そして自分が作成してみたコードは以下になります。

import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class TestAdapter extends BaseAdapter { private LayoutInflater inflater; private int layoutID; private String[] namelist; private String[] emaillist; private Bitmap[] photolist; TextView text; TextView email; ImageView img; TestAdapter(Context context, int itemLayoutId, String[] names, String[] emails, int[] photos ){ inflater = LayoutInflater.from(context); layoutID = itemLayoutId; namelist = names; emaillist = emails; // bitmapの配列 photolist = new Bitmap[photos.length]; // drawableのIDからbitmapに変換 for( int i = 0; i< photos.length; i++){ photolist[i] = BitmapFactory.decodeResource(context.getResources(), photos[i]); } } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = inflater.inflate(layoutID, null); img = convertView.findViewById(R.id.img_item); text = convertView.findViewById(R.id.text_view); email = convertView.findViewById(R.id.text_mail); convertView.setTag(img); convertView.setTag(text); convertView.setTag(email; } else { img = (ImageView) convertView.getTag(); text = (TextView) convertView.getTag(); email = (Texiview) convertView.getTag(); } img.setImageBitmap(photolist[position]); String str = "Staff ID.170900"+ String.valueOf(position+1) + "\n\nEmail: " + emaillist[position] + "\nTel: 020-8931-9933 #340" + String.valueOf(position+1); email.setText(str); text.setText(namelist[position]); return convertView; } @Override public int getCount() { return namelist.length; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } }

しかしこちらは
img = (ImageView) convertView.getTag(); の箇所にエラーが出てしまいました。
android.widget.TextView cannot be cast to android.widget.ImageView

TextView text;
TextView email;
ImageView img;

これらのものはclassで囲ってやって、
ViewHolder holder;  のようにして、
それを
holder.text
holder.email
holder.img
のように必ずしなくてはいけないのでしょうか?
質問の目的は、adapterそのものもありますが、それよりも
classとかjavaの文法、書き方、変数の書き方など基本的なことを知りたいため、
今回このような質問をさせていただきました。申し訳ございません;
乱れた文章でありますが申し訳ありません・・よろしくお願いいたします;

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ListView の Adapter には ViewHolder は必須ではありません。TestAdapter は ViewHolder をまるごと (TextView text; や TextView email; や ImageView img; も含めて) 削除して、getView メソッドを次のように書くことも可能です。

java

1 @Override 2 public View getView(int position, View convertView, ViewGroup parent) { 3 4 if (convertView == null) { 5 convertView = inflater.inflate(layoutID, null); 6 } 7 8 ImageView img = convertView.findViewById(R.id.img_item); 9 img.setImageBitmap(photolist[position]); 10 11 TextView email = convertView.findViewById(R.id.text_mail); 12 String str = "Staff ID.170900"+ String.valueOf(position+1) 13 + "\n\nEmail: " + emaillist[position] 14 + "\nTel: 020-8931-9933 #340" + String.valueOf(position+1); 15 email.setText(str); 16 17 TextView text = convertView.findViewById(R.id.text_view); 18 text.setText(namelist[position]); 19 20 return convertView; 21 }

ViewHolder を使う理由は、getView で毎回 findViewById しなくて済むようにすることによる性能向上 (および、各表示項目に関する追加の情報を持たせることもできる) ですが、この場合はそれほど複雑でもないので、誤差の範囲だと思います。

単純に ViewHolder の class を外してもうまくいかない理由ですが、TestAdapter は ListView と一対一対応しますが、ViewHolder は ListView に表示される複数の項目ひとつひとつに対して生成されるためです。
ちなみに、ListView ではリストの項目がどんなに増えても、getView で生成される View は実際に表示されてる分 (よりちょっと多く) しか生成されず、スクロールした際には画面からはみ出たものが再利用されます。(その場合、convertView は再利用される View が渡されます。) この辺の仕組みについては、表示するアイテムを使い回して節約--AndroidのListViewの営み あたりを読むと良いでしょう。

投稿2021/06/07 08:15

hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gugupoo

2021/06/07 23:55

有り難うございました!ViewHolderのところがよくわかりました。有り難うございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問