Java Android Studio-帮助我理解此代码

Java Android Studio-帮助我理解此代码,java,android,android-studio,layout-inflater,android-viewholder,Java,Android,Android Studio,Layout Inflater,Android Viewholder,我正在努力理解这段代码: 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) { viewHo

我正在努力理解这段代码:

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
部分

我的问题:

  • 为什么我必须创建一个名为
    ViewHolder
    私有类
    创建一个
    公共方法来存储我的所有视图(
    txtName,
    txtSinger、playB、stopB
    )并将其用于我的
    充气机
  • view.setTag(viewHolder)
    是什么意思
  • 在此上下文中,
    setTag
    getTag
    到底是什么
如果有人能帮我解决这个问题,这将非常有助于提高我对代码的理解

多谢各位

在此上下文中,setTag和getTag到底是什么

Android视图支持“标签”,这是可以附加到其上的任意对象。标签没有真正的定义,因为它们是你想要的。所有这些都同样有效:

  • view.setTag(2)
  • view.setTag(“Hello world”)
  • view.setTag(新对象())
view.setTag(viewHolder)是什么意思

您正在将
viewHolder
对象作为其标记附加到
view
。这本身并没有做任何事情,但它允许您稍后通过调用
(viewHolder)view.getTag()
来检索
viewHolder

为什么我必须创建一个名为ViewHolder[…]的私有类

使用
ListView
适配器时,有两件事会降低应用程序的性能:调用
inflate()
和调用
findViewById()

当传入的
视图
参数不为null时,使用传入的
视图
参数;当传入的
视图
参数为null时,仅调用
充气()。这就是您的代码:

您可以使用此“ViewHolder模式”绕过第二个窗口。您可以创建一个对象(视图保持器),以便在查找视图后“保持”视图。这就是您的代码:

完成该块后,将有一个名为
ViewHolder
ViewHolder
实例,您可以使用该实例直接访问视图。当传入的
view
参数为null时,您可以创建视图保持架,通过调用
findViewById()
填充它,并通过调用
setTag()
保存它。当传入的
view
参数不为null时,只需调用
getTag()
即可检索视图持有者

把这些放在一起,这意味着您可以编写如下代码:

而不是这个较慢的代码:

TextView txtName = view.findViewById(R.id.songName_text);
txtName.setText(song.getName());
在此上下文中,setTag和getTag到底是什么

Android视图支持“标签”,这是可以附加到其上的任意对象。标签没有真正的定义,因为它们是你想要的。所有这些都同样有效:

  • view.setTag(2)
  • view.setTag(“Hello world”)
  • view.setTag(新对象())
view.setTag(viewHolder)是什么意思

您正在将
viewHolder
对象作为其标记附加到
view
。这本身并没有做任何事情,但它允许您稍后通过调用
(viewHolder)view.getTag()
来检索
viewHolder

为什么我必须创建一个名为ViewHolder[…]的私有类

使用
ListView
适配器时,有两件事会降低应用程序的性能:调用
inflate()
和调用
findViewById()

当传入的
视图
参数不为null时,使用传入的
视图
参数;当传入的
视图
参数为null时,仅调用
充气()。这就是您的代码:

您可以使用此“ViewHolder模式”绕过第二个窗口。您可以创建一个对象(视图保持器),以便在查找视图后“保持”视图。这就是您的代码:

完成该块后,将有一个名为
ViewHolder
ViewHolder
实例,您可以使用该实例直接访问视图。当传入的
view
参数为null时,您可以创建视图保持架,通过调用
findViewById()
填充它,并通过调用
setTag()
保存它。当传入的
view
参数不为null时,只需调用
getTag()
即可检索视图持有者

把这些放在一起,这意味着您可以编写如下代码:

而不是这个较慢的代码:

TextView txtName = view.findViewById(R.id.songName_text);
txtName.setText(song.getName());

viewholder
是android应用程序中使用的一种设计模式,用于取代更昂贵的
findviewbyid
调用

报价文件

在滚动ListView期间,您的代码可能会频繁调用
findViewById()
,这会降低性能。即使适配器返回一个膨胀视图进行循环,您仍然需要查找元素并更新它们。反复使用
findViewById()
的一种方法是使用“视图保持器”设计模式

关于第二个和第三个问题,
settag
gettag
基本上是让您的视图拥有“记忆”的一种方式,您可以参考更多信息和更详细的解释


希望这有帮助

A
viewholder
是安卓应用程序中使用的一种设计模式,用于取代更昂贵的
findviewbyid
调用

报价文件

在滚动ListView期间,您的代码可能会频繁调用
findViewById()
,这会降低性能。即使适配器返回一个膨胀视图进行循环,您仍然需要查找元素并更新它们。避免重复使用
findViewById()
的一种方法是使用“视图”
viewHolder.txtName.setText(song.getName());
TextView txtName = view.findViewById(R.id.songName_text);
txtName.setText(song.getName());