java - Android Studio - 帮助我理解这段代码
问题描述
我试图理解这段代码:
private class ViewHolder {
TextView txtName, txtSinger;
ImageView playB, stopB;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
final ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
// inflate (create) another copy of our custom layout
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(layout, null);
viewHolder.txtName = (TextView) view.findViewById(R.id.songName_text);
viewHolder.txtSinger = (TextView) view.findViewById(R.id.singer_text);
viewHolder.playB = (ImageView) view.findViewById(R.id.play_png);
viewHolder.stopB = (ImageView) view.findViewById(R.id.stop_png);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
final Song song = arrayList.get(position);
// make changes to our custom layout and its subviews
viewHolder.txtName.setText(song.getName());
viewHolder.txtSinger.setText(song.getSinger());
// play music
viewHolder.playB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// MediaPlayer has not been initialized OR clicked song is not the currently loaded song
if (currentSong == null || song != currentSong) {
// Sets the currently loaded song
currentSong = song;
mediaPlayer = MediaPlayer.create(context, song.getSong());
Toast.makeText(context, "Playing: "+ song.getSinger() + " " + song.getName(), Toast.LENGTH_LONG).show();
}
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
viewHolder.playB.setImageResource(R.drawable.play);
} else {
mediaPlayer.start();
viewHolder.playB.setImageResource(R.drawable.pause);
}
}
});
// stop
viewHolder.stopB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// If currently loaded song is set the MediaPlayer must be initialized
if (currentSong != null) {
mediaPlayer.stop();
mediaPlayer.release();
currentSong = null; // Set back currently loaded song
}
viewHolder.playB.setImageResource(R.drawable.play);
}
});
return view;
}
但不是整个代码!让我困惑的部分是ViewHolder
部分。
我的问题:
- 为什么我必须创建一个
private class
被调用ViewHolder
而不是仅仅创建一个public method
来存储我的所有视图(txtName, txtSinger, playB, stopB
)并在我的中使用它inflater
? - 是什么
view.setTag(viewHolder)
意思? - 在这种情况下
setTag
究竟是什么?getTag
如果有人可以为我分解这一点,那将有助于我对代码的理解。
谢谢你。
解决方案
在这种情况下,setTag 和 getTag 到底是什么?
Android 视图支持“标签”,这是您可以附加到它们的任意对象。标签没有真正的定义,因为它们是您希望它们成为的任何东西。所有这些都同样有效:
view.setTag(2)
view.setTag("Hello world")
view.setTag(new Object())
view.setTag(viewHolder) 是什么意思?
您将viewHolder
对象view
作为其标签附加到。这本身不会做任何事情,但它允许您viewHolder
稍后通过调用(ViewHolder) view.getTag()
.
为什么我必须创建一个名为 ViewHolder 的私有类 [...]
当您使用ListView
适配器时,有两件事会降低应用程序的性能:调用inflate()
和调用findViewById()
。
您可以通过在传入参数不为空时使用传入的参数来绕过第一个view
,并且仅inflate()
在传入的view
参数为空时调用。这就是你的代码:
if (view == null) { ... LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(layout, null); ... } else { ... }
您可以使用此“ViewHolder 模式”绕过第二个。您创建一个对象(视图持有者)以在查找视图后“保存”视图。这就是你的代码:
final ViewHolder viewHolder; if (view == null) { viewHolder = new ViewHolder(); ... viewHolder.txtName = (TextView) view.findViewById(R.id.songName_text); viewHolder.txtSinger = (TextView) view.findViewById(R.id.singer_text); viewHolder.playB = (ImageView) view.findViewById(R.id.play_png); viewHolder.stopB = (ImageView) view.findViewById(R.id.stop_png); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); }
完成该块后,您将拥有一个ViewHolder
名为的实例viewHolder
,您可以使用该实例直接访问视图。当传入的view
参数为 null 时,您创建视图持有者,通过调用填充它findViewById()
,并通过调用保存它setTag()
。当传入的view
参数不为空时,您可以通过调用简单地检索视图持有者getTag()
。
将所有这些放在一起,这意味着您可以编写如下代码:
viewHolder.txtName.setText(song.getName());
而不是这个较慢的代码:
TextView txtName = view.findViewById(R.id.songName_text);
txtName.setText(song.getName());
推荐阅读
- r - 为什么我在 `[.data.frame`(data, , model.list$variables) 中出现错误:在 R 中选择了未定义的列?
- shopify - Weglot 将我的文字翻译两次,一个想法?
- bash - 在命令行中重复一个参数 N 次
- python - ImageDataBunch.from_folder 没有看到我的测试集
- java - AWS lambda 的 AmazonS3.readObject() 非常慢
- java - JHipster:org.apiguardian:apiguardian-api:1.1.0 的依赖收敛错误
- ios - 如何在 Combine 中对任意数量的 Bool Publisher 执行“全部”操作?
- html - 滚动时如何在 CSS 中转换图像
- matlab - 加载 MIT-BIH 心律失常数据库 (mitdb) ECG INTO MATLAB
- c# - 我如何在 C# 中拆分数组