Android Studio - Help me to understand this code











up vote
0
down vote

favorite












Im trying to understand this code:



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;
}


But not the whole code!
The part that is confusing me is the ViewHolder part.



My questions:




  • Why do i have to create a private class called ViewHolder instead
    of just creating a public method to store all my views (txtName,
    txtSinger, playB, stopB
    ) and use that in my inflater?

  • what does view.setTag(viewHolder) means?

  • What is exactly setTag and getTag in this context?


If anyone can break this down for me it would be very helpful to progress my understanding of code.



Thank you.










share|improve this question


























    up vote
    0
    down vote

    favorite












    Im trying to understand this code:



    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;
    }


    But not the whole code!
    The part that is confusing me is the ViewHolder part.



    My questions:




    • Why do i have to create a private class called ViewHolder instead
      of just creating a public method to store all my views (txtName,
      txtSinger, playB, stopB
      ) and use that in my inflater?

    • what does view.setTag(viewHolder) means?

    • What is exactly setTag and getTag in this context?


    If anyone can break this down for me it would be very helpful to progress my understanding of code.



    Thank you.










    share|improve this question
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      Im trying to understand this code:



      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;
      }


      But not the whole code!
      The part that is confusing me is the ViewHolder part.



      My questions:




      • Why do i have to create a private class called ViewHolder instead
        of just creating a public method to store all my views (txtName,
        txtSinger, playB, stopB
        ) and use that in my inflater?

      • what does view.setTag(viewHolder) means?

      • What is exactly setTag and getTag in this context?


      If anyone can break this down for me it would be very helpful to progress my understanding of code.



      Thank you.










      share|improve this question













      Im trying to understand this code:



      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;
      }


      But not the whole code!
      The part that is confusing me is the ViewHolder part.



      My questions:




      • Why do i have to create a private class called ViewHolder instead
        of just creating a public method to store all my views (txtName,
        txtSinger, playB, stopB
        ) and use that in my inflater?

      • what does view.setTag(viewHolder) means?

      • What is exactly setTag and getTag in this context?


      If anyone can break this down for me it would be very helpful to progress my understanding of code.



      Thank you.







      java android android-studio layout-inflater android-viewholder






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 9 at 22:39









      Delice

      236




      236
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted











          What is exactly setTag and getTag in this context?




          Android views support "tags", which are arbitrary objects you can attach to them. There's no real definition for tags, because they're whatever you want them to be. All of these are equally valid:




          • view.setTag(2)

          • view.setTag("Hello world")

          • view.setTag(new Object())



          what does view.setTag(viewHolder) means?




          You're attaching the viewHolder object to view as its tag. This doesn't do anything by itself, but it lets you retrieve the viewHolder later on by calling (ViewHolder) view.getTag().




          Why do i have to create a private class called ViewHolder [...]




          When you're working with ListView adapters, there are two things that can slow the performance of your app way down: calling inflate() and calling findViewById().



          You get around the first by using the passed-in view argument when it's not null, and only calling inflate() when the passed in view argument is null. That's this bit of your code:




          if (view == null) {
          ...
          LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          view = layoutInflater.inflate(layout, null);
          ...
          } else {
          ...
          }



          You get around the second by using this "ViewHolder pattern". You create an object (the view holder) to "hold" the views after you look them up. That's this bit of your code:




          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();
          }



          Once that block is done, you'll have a ViewHolder instance named viewHolder that you can use to access views directly. When the passed-in view argument is null, you create the view holder, populate it by calling findViewById(), and save it by calling setTag(). When the passed-in view argument is not null, you can simply retrieve the view holder by calling getTag().



          Put that all together, and that means you can write code like this:




          viewHolder.txtName.setText(song.getName());



          Instead of this slower code:



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





          share|improve this answer





















          • I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
            – Delice
            Nov 9 at 23:35










          • Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
            – Ben P.
            Nov 9 at 23:42










          • I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
            – Delice
            Nov 9 at 23:54






          • 1




            I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
            – Ben P.
            Nov 10 at 3:24










          • Ok thanks I think i got it now!
            – Delice
            Nov 10 at 13:36


















          up vote
          1
          down vote













          A viewholder is a design pattern used in android apps in order to replace the more expensive findviewbyid calls.



          Quoting docs



          Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.



          Regarding the second and third question the settag and gettag is basically a way for your view to have "memories" you can refer here for further information and a more detailed explanation!



          Hope this helps!






          share|improve this answer





















          • Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
            – Delice
            Nov 9 at 23:36











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234158%2fandroid-studio-help-me-to-understand-this-code%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote



          accepted











          What is exactly setTag and getTag in this context?




          Android views support "tags", which are arbitrary objects you can attach to them. There's no real definition for tags, because they're whatever you want them to be. All of these are equally valid:




          • view.setTag(2)

          • view.setTag("Hello world")

          • view.setTag(new Object())



          what does view.setTag(viewHolder) means?




          You're attaching the viewHolder object to view as its tag. This doesn't do anything by itself, but it lets you retrieve the viewHolder later on by calling (ViewHolder) view.getTag().




          Why do i have to create a private class called ViewHolder [...]




          When you're working with ListView adapters, there are two things that can slow the performance of your app way down: calling inflate() and calling findViewById().



          You get around the first by using the passed-in view argument when it's not null, and only calling inflate() when the passed in view argument is null. That's this bit of your code:




          if (view == null) {
          ...
          LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          view = layoutInflater.inflate(layout, null);
          ...
          } else {
          ...
          }



          You get around the second by using this "ViewHolder pattern". You create an object (the view holder) to "hold" the views after you look them up. That's this bit of your code:




          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();
          }



          Once that block is done, you'll have a ViewHolder instance named viewHolder that you can use to access views directly. When the passed-in view argument is null, you create the view holder, populate it by calling findViewById(), and save it by calling setTag(). When the passed-in view argument is not null, you can simply retrieve the view holder by calling getTag().



          Put that all together, and that means you can write code like this:




          viewHolder.txtName.setText(song.getName());



          Instead of this slower code:



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





          share|improve this answer





















          • I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
            – Delice
            Nov 9 at 23:35










          • Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
            – Ben P.
            Nov 9 at 23:42










          • I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
            – Delice
            Nov 9 at 23:54






          • 1




            I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
            – Ben P.
            Nov 10 at 3:24










          • Ok thanks I think i got it now!
            – Delice
            Nov 10 at 13:36















          up vote
          1
          down vote



          accepted











          What is exactly setTag and getTag in this context?




          Android views support "tags", which are arbitrary objects you can attach to them. There's no real definition for tags, because they're whatever you want them to be. All of these are equally valid:




          • view.setTag(2)

          • view.setTag("Hello world")

          • view.setTag(new Object())



          what does view.setTag(viewHolder) means?




          You're attaching the viewHolder object to view as its tag. This doesn't do anything by itself, but it lets you retrieve the viewHolder later on by calling (ViewHolder) view.getTag().




          Why do i have to create a private class called ViewHolder [...]




          When you're working with ListView adapters, there are two things that can slow the performance of your app way down: calling inflate() and calling findViewById().



          You get around the first by using the passed-in view argument when it's not null, and only calling inflate() when the passed in view argument is null. That's this bit of your code:




          if (view == null) {
          ...
          LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          view = layoutInflater.inflate(layout, null);
          ...
          } else {
          ...
          }



          You get around the second by using this "ViewHolder pattern". You create an object (the view holder) to "hold" the views after you look them up. That's this bit of your code:




          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();
          }



          Once that block is done, you'll have a ViewHolder instance named viewHolder that you can use to access views directly. When the passed-in view argument is null, you create the view holder, populate it by calling findViewById(), and save it by calling setTag(). When the passed-in view argument is not null, you can simply retrieve the view holder by calling getTag().



          Put that all together, and that means you can write code like this:




          viewHolder.txtName.setText(song.getName());



          Instead of this slower code:



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





          share|improve this answer





















          • I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
            – Delice
            Nov 9 at 23:35










          • Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
            – Ben P.
            Nov 9 at 23:42










          • I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
            – Delice
            Nov 9 at 23:54






          • 1




            I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
            – Ben P.
            Nov 10 at 3:24










          • Ok thanks I think i got it now!
            – Delice
            Nov 10 at 13:36













          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted







          What is exactly setTag and getTag in this context?




          Android views support "tags", which are arbitrary objects you can attach to them. There's no real definition for tags, because they're whatever you want them to be. All of these are equally valid:




          • view.setTag(2)

          • view.setTag("Hello world")

          • view.setTag(new Object())



          what does view.setTag(viewHolder) means?




          You're attaching the viewHolder object to view as its tag. This doesn't do anything by itself, but it lets you retrieve the viewHolder later on by calling (ViewHolder) view.getTag().




          Why do i have to create a private class called ViewHolder [...]




          When you're working with ListView adapters, there are two things that can slow the performance of your app way down: calling inflate() and calling findViewById().



          You get around the first by using the passed-in view argument when it's not null, and only calling inflate() when the passed in view argument is null. That's this bit of your code:




          if (view == null) {
          ...
          LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          view = layoutInflater.inflate(layout, null);
          ...
          } else {
          ...
          }



          You get around the second by using this "ViewHolder pattern". You create an object (the view holder) to "hold" the views after you look them up. That's this bit of your code:




          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();
          }



          Once that block is done, you'll have a ViewHolder instance named viewHolder that you can use to access views directly. When the passed-in view argument is null, you create the view holder, populate it by calling findViewById(), and save it by calling setTag(). When the passed-in view argument is not null, you can simply retrieve the view holder by calling getTag().



          Put that all together, and that means you can write code like this:




          viewHolder.txtName.setText(song.getName());



          Instead of this slower code:



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





          share|improve this answer













          What is exactly setTag and getTag in this context?




          Android views support "tags", which are arbitrary objects you can attach to them. There's no real definition for tags, because they're whatever you want them to be. All of these are equally valid:




          • view.setTag(2)

          • view.setTag("Hello world")

          • view.setTag(new Object())



          what does view.setTag(viewHolder) means?




          You're attaching the viewHolder object to view as its tag. This doesn't do anything by itself, but it lets you retrieve the viewHolder later on by calling (ViewHolder) view.getTag().




          Why do i have to create a private class called ViewHolder [...]




          When you're working with ListView adapters, there are two things that can slow the performance of your app way down: calling inflate() and calling findViewById().



          You get around the first by using the passed-in view argument when it's not null, and only calling inflate() when the passed in view argument is null. That's this bit of your code:




          if (view == null) {
          ...
          LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          view = layoutInflater.inflate(layout, null);
          ...
          } else {
          ...
          }



          You get around the second by using this "ViewHolder pattern". You create an object (the view holder) to "hold" the views after you look them up. That's this bit of your code:




          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();
          }



          Once that block is done, you'll have a ViewHolder instance named viewHolder that you can use to access views directly. When the passed-in view argument is null, you create the view holder, populate it by calling findViewById(), and save it by calling setTag(). When the passed-in view argument is not null, you can simply retrieve the view holder by calling getTag().



          Put that all together, and that means you can write code like this:




          viewHolder.txtName.setText(song.getName());



          Instead of this slower code:



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






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 9 at 22:49









          Ben P.

          22k31846




          22k31846












          • I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
            – Delice
            Nov 9 at 23:35










          • Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
            – Ben P.
            Nov 9 at 23:42










          • I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
            – Delice
            Nov 9 at 23:54






          • 1




            I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
            – Ben P.
            Nov 10 at 3:24










          • Ok thanks I think i got it now!
            – Delice
            Nov 10 at 13:36


















          • I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
            – Delice
            Nov 9 at 23:35










          • Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
            – Ben P.
            Nov 9 at 23:42










          • I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
            – Delice
            Nov 9 at 23:54






          • 1




            I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
            – Ben P.
            Nov 10 at 3:24










          • Ok thanks I think i got it now!
            – Delice
            Nov 10 at 13:36
















          I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
          – Delice
          Nov 9 at 23:35




          I have a question regarding the 3th question you answered "Why do i have to create a private class called ViewHolder [...]" --> Why does it have to be a class? is it possible to make it a public method ?
          – Delice
          Nov 9 at 23:35












          Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
          – Ben P.
          Nov 9 at 23:42




          Why do you want it to be a method? But, short answer, no. You can only pass objects to setTag(), so you have to define a class for your view holder.
          – Ben P.
          Nov 9 at 23:42












          I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
          – Delice
          Nov 9 at 23:54




          I've had an older project where i made a public method called myViews() that i used in my onCreate method in an if-statement.. so i just wondered why i had to use class this time.
          – Delice
          Nov 9 at 23:54




          1




          1




          I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
          – Ben P.
          Nov 10 at 3:24




          I think the major difference here is that, when you have just one Activity, you can use a method to organize all of your findViewById() calls... but in this case you have a different view holder for every row, so you need many different "groups" of findViewById() calls. A view holder object/class is the best way to do that.
          – Ben P.
          Nov 10 at 3:24












          Ok thanks I think i got it now!
          – Delice
          Nov 10 at 13:36




          Ok thanks I think i got it now!
          – Delice
          Nov 10 at 13:36












          up vote
          1
          down vote













          A viewholder is a design pattern used in android apps in order to replace the more expensive findviewbyid calls.



          Quoting docs



          Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.



          Regarding the second and third question the settag and gettag is basically a way for your view to have "memories" you can refer here for further information and a more detailed explanation!



          Hope this helps!






          share|improve this answer





















          • Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
            – Delice
            Nov 9 at 23:36















          up vote
          1
          down vote













          A viewholder is a design pattern used in android apps in order to replace the more expensive findviewbyid calls.



          Quoting docs



          Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.



          Regarding the second and third question the settag and gettag is basically a way for your view to have "memories" you can refer here for further information and a more detailed explanation!



          Hope this helps!






          share|improve this answer





















          • Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
            – Delice
            Nov 9 at 23:36













          up vote
          1
          down vote










          up vote
          1
          down vote









          A viewholder is a design pattern used in android apps in order to replace the more expensive findviewbyid calls.



          Quoting docs



          Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.



          Regarding the second and third question the settag and gettag is basically a way for your view to have "memories" you can refer here for further information and a more detailed explanation!



          Hope this helps!






          share|improve this answer












          A viewholder is a design pattern used in android apps in order to replace the more expensive findviewbyid calls.



          Quoting docs



          Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.



          Regarding the second and third question the settag and gettag is basically a way for your view to have "memories" you can refer here for further information and a more detailed explanation!



          Hope this helps!







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 9 at 23:00









          Georgios S.

          1799




          1799












          • Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
            – Delice
            Nov 9 at 23:36


















          • Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
            – Delice
            Nov 9 at 23:36
















          Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
          – Delice
          Nov 9 at 23:36




          Thank you for your input! I think i almost understood everything. I just need to verify one last question and i put that into Ben P. answer.
          – Delice
          Nov 9 at 23:36


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234158%2fandroid-studio-help-me-to-understand-this-code%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Academy of Television Arts & Sciences

          L'Équipe

          1995 France bombings