<?xml version="1.0" encoding="UTF-8"?>
<rss version='2.0' xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Rany Albeg Wein</title>
    <description>Android stuff</description>
    <link>https://ranyalbegwein.silvrback.com/feed</link>
    <atom:link href="https://ranyalbegwein.silvrback.com/feed" rel="self" type="application/rss+xml"/>
    <category domain="ranyalbegwein.silvrback.com">Content Management/Blog</category>
    <language>en-us</language>
      <pubDate>Wed, 27 Sep 2017 01:14:26 +0300</pubDate>
    <managingEditor>rany.albeg@gmail.com (Rany Albeg Wein)</managingEditor>
      <item>
        <guid>https://ranyalbegwein.silvrback.com/transforming-image-behavior#34552</guid>
          <pubDate>Wed, 27 Sep 2017 01:14:26 +0300</pubDate>
        <link>https://ranyalbegwein.silvrback.com/transforming-image-behavior</link>
        <title>Creating a custom CoordinatorLayout Behavior</title>
        <description></description>
        <content:encoded><![CDATA[<h1 id="1-intro">1. Intro</h1>

<p>Trust me, it&#39;s not as complicated as it might first look like. You either drink too much coffee, or need to take your face off of the screen for a while.</p>

<p>A <code>CoordinatorLayout</code> is this thing:</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CoordinatorLayout</span> <span class="kd">extends</span> <span class="n">ViewGroup</span> <span class="kd">implements</span> <span class="n">NestedScrollingParent</span> <span class="o">{</span>
    <span class="o">...</span> 
<span class="o">}</span>
</pre></div>
<p>from the support library ( <code>compile &#39;com.android.support:design:25.3.1&#39;</code> ), which seems at first like an innocent old <code>FrameLayout</code>, until you discover its real powers - <code>Behavior</code>s!</p>

<p>A <code>Behavior</code> is an object attached to a child of  a <code>CoordinatorLayout</code>, which defines its interaction with another <code>View</code>, ( a <em>dependency</em>) within the same layout.</p>

<p>So, a <code>CoordinatorLayout</code> monitors every movement of its children, and notifies the ones with attached <code>Behavior</code>s for a <em>dependency</em> change. </p>

<p>Something like this:</p>

<p><img alt="Silvrback blog image" class="sb_float_center" src="https://silvrback.s3.amazonaws.com/uploads/6500b8c4-10f1-4fe7-ada1-04e5c6ccb17e/PicsArt_09-24-01.54.31.jpg" /></p>

<p>The <code>SnackBar</code> here is called a <em>dependency</em> - which makes sense, because the child <strong>depends</strong> on its movement in order to behave in a certain way specified by its attached <code>Behavior</code>.</p>

<p>Following <em>Material Design</em> guidelines, this behavior is the correct interaction between a <code>SnackBar</code> and a <code>FloatingActionButton</code>. </p>

<h1 id="2-lets-get-started">2. Let&#39;s get started!</h1>

<p>Everything should run in a context or under the supervision of a <code>CoordinatorLayout</code>, so let&#39;s create a fresh Activity with a <code>CoordinatorLayout</code> as its content-view root element.</p>

<p>Create a new project, and add a new Activity by selecting the &quot;Basic Activity&quot; template:<br>
<img alt="Silvrback blog image " src="https://silvrback.s3.amazonaws.com/uploads/af1e9c49-b5d1-49c4-a1a9-98ae94e32122/screen-capture-4wZio.jpg" /></p>

<p>Take a look at <em>activity_main.xml</em>, it should contain the following:</p>
<div class="highlight"><pre><span></span><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span>
<span class="nt">&lt;android.support.design.widget.CoordinatorLayout</span>
    <span class="na">xmlns:android=</span><span class="s">&quot;http://schemas.android.com/apk/res/android&quot;</span>
    <span class="na">xmlns:app=</span><span class="s">&quot;http://schemas.android.com/apk/res-auto&quot;</span>
    <span class="na">xmlns:tools=</span><span class="s">&quot;http://schemas.android.com/tools&quot;</span>
    <span class="na">android:layout_width=</span><span class="s">&quot;match_parent&quot;</span>
    <span class="na">android:layout_height=</span><span class="s">&quot;match_parent&quot;</span>
    <span class="na">tools:context=</span><span class="s">&quot;com.rany.albeg.wein.behaviors.MainActivity&quot;</span><span class="nt">&gt;</span>

    <span class="nt">&lt;android.support.design.widget.AppBarLayout</span>
        <span class="na">android:layout_height=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_width=</span><span class="s">&quot;match_parent&quot;</span>
        <span class="na">android:theme=</span><span class="s">&quot;@style/AppTheme.AppBarOverlay&quot;</span><span class="nt">&gt;</span>

        <span class="nt">&lt;android.support.v7.widget.Toolbar</span>
            <span class="na">android:id=</span><span class="s">&quot;@+id/toolbar&quot;</span>
            <span class="na">android:layout_width=</span><span class="s">&quot;match_parent&quot;</span>
            <span class="na">android:layout_height=</span><span class="s">&quot;?attr/actionBarSize&quot;</span>
            <span class="na">android:background=</span><span class="s">&quot;?attr/colorPrimary&quot;</span>
            <span class="na">app:popupTheme=</span><span class="s">&quot;@style/AppTheme.PopupOverlay&quot;</span> <span class="nt">/&gt;</span>

    <span class="nt">&lt;/android.support.design.widget.AppBarLayout&gt;</span>

    <span class="nt">&lt;include</span> <span class="na">layout=</span><span class="s">&quot;@layout/content_main&quot;</span><span class="nt">/&gt;</span>

    <span class="nt">&lt;android.support.design.widget.FloatingActionButton</span>
        <span class="na">android:id=</span><span class="s">&quot;@+id/fab&quot;</span>
        <span class="na">android:layout_width=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_height=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_gravity=</span><span class="s">&quot;bottom|end&quot;</span>
        <span class="na">android:layout_margin=</span><span class="s">&quot;@dimen/fab_margin&quot;</span>
        <span class="na">app:srcCompat=</span><span class="s">&quot;@android:drawable/ic_dialog_email&quot;</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;/android.support.design.widget.CoordinatorLayout&gt;</span>
</pre></div>
<p>Since the default behavior of <code>FloatingActionButton</code> is to run away from the <code>SnackBar</code> like we wish to implement ourselves, take it off of the XML tree and insert something like an <code>AppCompatButton</code>:</p>
<div class="highlight"><pre><span></span><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span>
<span class="nt">&lt;android.support.design.widget.CoordinatorLayout&gt;</span>

     ...

    <span class="nt">&lt;android.support.v7.widget.AppCompatButton</span>
        <span class="na">android:id=</span><span class="s">&quot;@+id/bt_click_me&quot;</span>
        <span class="na">android:layout_width=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_height=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_gravity=</span><span class="s">&quot;bottom|end&quot;</span>
        <span class="na">android:layout_margin=</span><span class="s">&quot;16dp&quot;</span>
        <span class="na">android:text=</span><span class="s">&quot;Click me&quot;</span><span class="nt">/&gt;</span>

<span class="nt">&lt;/android.support.design.widget.CoordinatorLayout&gt;</span>
</pre></div>
<p>Edit <code>MainActivity</code> accordingly, and modify <code>onCreate()</code>:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@Override</span>
    <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onCreate</span><span class="o">(</span><span class="n">Bundle</span> <span class="n">savedInstanceState</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">.</span><span class="na">onCreate</span><span class="o">(</span><span class="n">savedInstanceState</span><span class="o">);</span>
        <span class="n">setContentView</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">layout</span><span class="o">.</span><span class="na">activity_main</span><span class="o">);</span>
        <span class="n">Toolbar</span> <span class="n">toolbar</span> <span class="o">=</span> <span class="o">(</span><span class="n">Toolbar</span><span class="o">)</span> <span class="n">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">toolbar</span><span class="o">);</span>
        <span class="n">setSupportActionBar</span><span class="o">(</span><span class="n">toolbar</span><span class="o">);</span>

        <span class="n">AppCompatButton</span> <span class="n">btn</span> <span class="o">=</span> <span class="o">(</span><span class="n">AppCompatButton</span><span class="o">)</span> <span class="n">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">bt_click_me</span><span class="o">);</span>
        <span class="n">btn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">new</span> <span class="n">View</span><span class="o">.</span><span class="na">OnClickListener</span><span class="o">()</span> <span class="o">{</span>
            <span class="nd">@Override</span>
            <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onClick</span><span class="o">(</span><span class="n">View</span> <span class="n">view</span><span class="o">)</span> <span class="o">{</span>
                <span class="n">Snackbar</span><span class="o">.</span><span class="na">make</span><span class="o">(</span><span class="n">view</span><span class="o">,</span> <span class="s">&quot;Yeah buddy!&quot;</span><span class="o">,</span> <span class="n">Snackbar</span><span class="o">.</span><span class="na">LENGTH_LONG</span><span class="o">)</span>
                        <span class="o">.</span><span class="na">setAction</span><span class="o">(</span><span class="s">&quot;Action&quot;</span><span class="o">,</span> <span class="kc">null</span><span class="o">).</span><span class="na">show</span><span class="o">();</span>
            <span class="o">}</span>
        <span class="o">});</span>
    <span class="o">}</span>
</pre></div>
<h1 id="3-implementation">3. Implementation</h1>

<p>To create a <code>Behavior</code> we&#39;ll need to create a class that extends <code>CoordinatorLayout.Behavior&lt;V&gt;</code> where <code>V</code> is a type of a class which extends <code>View</code> and represents the type of the child -  in our case it&#39;ll be <code>AppCompatButton</code>:</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CustomMoveUpBehavior</span> <span class="kd">extends</span> 
                                  <span class="n">CoordinatorLayout</span><span class="o">.</span><span class="na">Behavior</span><span class="o">&lt;</span><span class="n">AppCompatButton</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="o">...</span>
<span class="o">}</span>
</pre></div>
<p>We&#39;re almost done! To complete programming our custom behavior and define the unique interaction between a child and a dependency, we&#39;ll need to:</p>

<ul>
<li>Override <code>layoutDependsOn(...)</code></li>
</ul>

<p>This method gets called ( at least once in response to a layout request ) by the parent <code>CoordinatorLayout</code> to determine whether the supplied child view has another specific sibling view as a layout dependency.<br>
In other words, <code>CoordinatorLayout</code> sees the <code>SnackBar</code> and asks us :</p>

<p><em>&quot;Hey, is this AppCompatButton depends on this SnackBar ?&quot;</em> and we should answer  <em>&quot;Yes!&quot;</em> in order to further react in accordance to <code>SnackBar</code>&#39;s movement:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">layoutDependsOn</span><span class="o">(</span><span class="n">CoordinatorLayout</span> <span class="n">parent</span><span class="o">,</span>
                                   <span class="n">AppCompatButton</span> <span class="n">child</span><span class="o">,</span>
                                   <span class="n">View</span> <span class="n">dependency</span><span class="o">)</span> <span class="o">{</span>

        <span class="k">return</span> <span class="n">dependency</span> <span class="k">instanceof</span> <span class="n">Snackbar</span><span class="o">.</span><span class="na">SnackbarLayout</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div>
<ul>
<li>Override <code>onDependentViewChanged(...)</code></li>
</ul>

<p>This method gets called by the parent <code>CoordinatorLayout</code> after the relevant <code>layoutDependsOn(...)</code> returns <code>true</code>, in which we need to actually move stuff!</p>

<p>In our case, for the button to run away from the <code>SnackBar</code>, we&#39;ll want to translate its Y position to be the difference between <code>SnackBar</code>&#39;s current Y translation and its height!</p>
<div class="highlight"><pre><span></span>    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">onDependentViewChanged</span><span class="o">(</span><span class="n">CoordinatorLayout</span> <span class="n">parent</span><span class="o">,</span>
                                          <span class="n">AppCompatButton</span> <span class="n">child</span><span class="o">,</span>
                                          <span class="n">View</span> <span class="n">dependency</span><span class="o">)</span> <span class="o">{</span>

        <span class="kt">float</span> <span class="n">tY</span> <span class="o">=</span> <span class="n">dependency</span><span class="o">.</span><span class="na">getTranslationY</span><span class="o">()</span> <span class="o">-</span> <span class="n">dependency</span><span class="o">.</span><span class="na">getHeight</span><span class="o">();</span>
        <span class="n">child</span><span class="o">.</span><span class="na">setTranslationY</span><span class="o">(</span><span class="n">tY</span><span class="o">);</span>
        <span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div>
<p>We return <code>true</code> to say:  <em>&quot;Hey CoordinatorLayout! Our Behavior changed AppCompatButton&#39;s position&quot;</em></p>

<p><code>CustomMoveUpBehavior</code> is done and ready to be attached!</p>

<p>There are several ways to attach a <code>Behavior</code> to <code>View</code>, and I&#39;ll choose to go with the common way - via XML.</p>

<p>In order to attach <code>CustomMoveUpBehavior</code> to <code>AppCompatButton</code> via XML, add the following constructor first:</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="nf">CustomMoveUpBehavior</span><span class="o">(</span><span class="n">Context</span> <span class="n">context</span><span class="o">,</span> <span class="n">AttributeSet</span> <span class="n">attrs</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">(</span><span class="n">context</span><span class="o">,</span> <span class="n">attrs</span><span class="o">);</span>
<span class="o">}</span>
</pre></div>
<p>and now jump into <code>activity_main.xml</code> and just add the following attribute to <code>AppCompatButton</code>&#39;s XML tag:</p>
<div class="highlight"><pre><span></span>    <span class="nt">&lt;android.support.v7.widget.AppCompatButton</span>
    <span class="err">...</span>
        <span class="na">app:layout_behavior=</span><span class="s">&quot;your.package.name.CustomMoveUpBehavior&quot;</span>
    <span class="err">...</span>
    <span class="nt">/&gt;</span>
</pre></div>
<p>replacing <em>your.package.name</em> as necessary.</p>

<p>Play it!<br>
<img alt="Silvrback blog image " src="https://silvrback.s3.amazonaws.com/uploads/f8777d22-a293-4ac8-80ff-c717cfc42a98/PicsArt_09-27-12.57.09_large.jpg" /></p>

<hr>

<h1 id="want-to-support-this-kind-of-content-buy-rany-a-coffee">Want to support this kind of content ? <a href="https://ko-fi.com/E1E0B4X4">Buy Rany a Coffee</a></h1>
]]></content:encoded>
      </item>
      <item>
        <guid>https://ranyalbegwein.silvrback.com/writing-basic-recyclerview-adapter#28701</guid>
          <pubDate>Fri, 02 Dec 2016 16:07:00 +0200</pubDate>
        <link>https://ranyalbegwein.silvrback.com/writing-basic-recyclerview-adapter</link>
        <title>Writing a basic RecyclerView.Adapter	 </title>
        <description>and how it is similar to a typical getView() implementation</description>
        <content:encoded><![CDATA[<p>In my previous article, <a href="https://ranyalbegwein.silvrback.com/listview-and-viewholder">ListView and ViewHolder</a>, I discussed about the <strong>ViewHolder</strong> pattern and how it should be combined to be a part of an adapter for a <strong>ListView</strong>, or more specifically - a part of an adapter&#39;s <code>getView()</code> method.<br>
We had a simple model named <strong>Profile</strong>, which describes some basic information of a person. It has an <em>image</em>, a <em>name</em> and a short <em>bio</em>:</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Profile</span> <span class="o">{</span>
    <span class="cm">/**</span>
<span class="cm">     * Name of person.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">mName</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * Bio.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">mBio</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * Profile image resource.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">mProfileImageResource</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">Profile</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">String</span> <span class="n">bio</span><span class="o">,</span> <span class="kt">int</span> <span class="n">profileImageResource</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">mName</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
        <span class="n">mBio</span> <span class="o">=</span> <span class="n">bio</span><span class="o">;</span>
        <span class="n">mProfileImageResource</span> <span class="o">=</span> <span class="n">profileImageResource</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="cm">/* &quot;Get&quot; methods... */</span>
<span class="o">}</span>
</pre></div>
<p>Our adapter, <strong>MyArrayAdapter</strong>, mapped <strong>Profile</strong>&#39;s three members ( <em>name</em>, <em>bio</em> and <em>image</em> ) to matching <strong>View</strong>s in our layout  (<code>R.layout.list_item</code>): two <strong>TextView</strong>s for <em>name</em> and <em>bio</em> and an <strong>ImageView</strong> for the <em>image</em>. Let&#39;s remember that instead of using <code>findViewById()</code> multiple times ( to find these three <strong>View</strong>s as <code>getView()</code> is being called ), we created a <strong>ViewHolder</strong> and used it to map a <strong>Profile</strong> to a visual layout.</p>

<p>This <em>mapping</em> process is called <em>binding</em>. We can say that we <strong>bind</strong> <strong>ViewHolder</strong>&#39;s members ( Our layout&#39;s <strong>View</strong>s ) to a <strong>Profile</strong>.<br>
If we first <strong>create</strong> a <strong>ViewHolder</strong> and  then <strong>bind</strong> a <strong>ViewHolder</strong>, wouldn&#39;t it make sense to split these two tasks into two methods <code>onCreateViewHolder()</code> and <code>onBindViewHolder()</code> ?<br>
This is <strong>exactly</strong> what <strong>RecyclerView.Adapter</strong> does!</p>

<p><strong>RecyclerView.Adapter</strong> declares two <code>abstract</code> methods which we obviously must implement when we extend it:</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">abstract</span> <span class="n">VH</span> <span class="nf">onCreateViewHolder</span><span class="o">(</span><span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">,</span> <span class="kt">int</span> <span class="n">viewType</span><span class="o">);</span>
</pre></div><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">abstract</span> <span class="kt">void</span> <span class="nf">onBindViewHolder</span><span class="o">(</span><span class="n">VH</span> <span class="n">holder</span><span class="o">,</span> <span class="kt">int</span> <span class="n">position</span><span class="o">);</span>
</pre></div>
<p><strong>RecyclerView.Adapter</strong> is responsible for invoking these two methods whenever there&#39;s a need to create or bind a <strong>ViewHolder</strong>.<br>
You can see that <code>onCreateViewHolder()</code> returns a <code>VH</code> type, and I can tell you that <code>onBindViewHolder()</code> receives this exact returned value as an argument. <code>VH</code> stands for <strong>V</strong>iew <strong>H</strong>older and it&#39;s a generic type which needs to extend <strong>RecyclerView.ViewHolder</strong> and which we need to implement. Let&#39;s call it <strong>MyViewHolder</strong> :</p>
<div class="highlight"><pre><span></span>    <span class="kd">class</span> <span class="nc">MyViewHolder</span> <span class="kd">extends</span> <span class="n">RecyclerView</span><span class="o">.</span><span class="na">ViewHolder</span> <span class="o">{</span>
        <span class="n">TextView</span> <span class="n">name</span><span class="o">;</span>
        <span class="n">TextView</span> <span class="n">bio</span><span class="o">;</span>
        <span class="n">ImageView</span> <span class="n">img</span><span class="o">;</span>

        <span class="n">MyViewHolder</span><span class="o">(</span><span class="n">View</span> <span class="n">itemView</span><span class="o">)</span> <span class="o">{</span>
            <span class="kd">super</span><span class="o">(</span><span class="n">itemView</span><span class="o">);</span>
            <span class="n">name</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">itemView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_name</span><span class="o">);</span>
            <span class="n">bio</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">itemView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_bio</span><span class="o">);</span>
            <span class="n">img</span> <span class="o">=</span> <span class="o">(</span><span class="n">ImageView</span><span class="o">)</span> <span class="n">itemView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">iv_profile_image</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
</pre></div>
<p>In its constructor, <strong>MyViewHolder</strong> receives the <code>itemView</code> argument, which is the inflated layout (<code>R.layout.list_item</code>) in which and by which we find all other child views: <em>name</em>, <em>bio</em> and <em>img</em>.<br>
<strong>MyViewHolder</strong>&#39;s constructor executes a series of calls to <code>findViewById()</code>, one for each <strong>View</strong> in our layout and keeps references to each one of the <strong>View</strong>s.</p>

<p>To get a better idea on how to implement <code>onCreateViewHolder()</code> and <code>onBindViewHolder()</code> having <strong>MyViewHolder</strong> implementation, let&#39;s look at their similarity with our already implemented <code>getView()</code> in the previous article - <a href="https://ranyalbegwein.silvrback.com/listview-and-viewholder">ListView and ViewHolder</a></p>

<p><img alt="Silvrback blog image" src="https://silvrback.s3.amazonaws.com/uploads/e6c098de-e9df-4d0a-8013-ad1103ef9e39/similarity_with_getview_large.jpg" /></p>

<p>OK, things are getting more clear now.<code>onBindViewHolder()</code>&#39;s implementation is just a copy-paste task:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onBindViewHolder</span><span class="o">(</span><span class="n">MyViewHolder</span> <span class="n">holder</span><span class="o">,</span> <span class="kt">int</span> <span class="n">position</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">final</span> <span class="n">Profile</span> <span class="n">profile</span> <span class="o">=</span> <span class="n">mProfiles</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">position</span><span class="o">);</span>
        <span class="n">holder</span><span class="o">.</span><span class="na">name</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
        <span class="n">holder</span><span class="o">.</span><span class="na">bio</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getBio</span><span class="o">());</span>
        <span class="n">holder</span><span class="o">.</span><span class="na">img</span><span class="o">.</span><span class="na">setImageResource</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getProfileImageResource</span><span class="o">());</span>
    <span class="o">}</span>
</pre></div>
<p>Finally, we can write <code>onCreateViewHolder()</code> to create a <strong>MyViewHolder</strong> and return it, so that <code>onBindViewHolder()</code> will receive it as an argument later and continue with the binding process:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">MyViewHolder</span> <span class="nf">onCreateViewHolder</span><span class="o">(</span><span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">,</span> <span class="kt">int</span> <span class="n">viewType</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">final</span> <span class="n">View</span> <span class="n">itemView</span> <span class="o">=</span> <span class="n">View</span><span class="o">.</span><span class="na">inflate</span><span class="o">(</span><span class="n">mContext</span><span class="o">,</span> <span class="n">R</span><span class="o">.</span><span class="na">layout</span><span class="o">.</span><span class="na">list_item</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">MyViewHolder</span><span class="o">(</span><span class="n">itemView</span><span class="o">);</span>
    <span class="o">}</span>
</pre></div>
<p>Connecting all the pieces, we can now write our adapter - <strong>MyProfilesAdapter</strong> :</p>
<div class="highlight"><pre><span></span><span class="kd">class</span> <span class="nc">MyProfilesAdapter</span> <span class="kd">extends</span> <span class="n">RecyclerView</span><span class="o">.</span><span class="na">Adapter</span><span class="o">&lt;</span><span class="n">MyProfilesAdapter</span><span class="o">.</span><span class="na">MyViewHolder</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="n">Context</span> <span class="n">mContext</span><span class="o">;</span>
    <span class="kd">private</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">Profile</span><span class="o">&gt;</span> <span class="n">mProfiles</span> <span class="o">=</span> <span class="n">Collections</span><span class="o">.</span><span class="na">emptyList</span><span class="o">();</span>

    <span class="n">MyProfilesAdapter</span><span class="o">(</span><span class="n">Context</span> <span class="n">context</span><span class="o">,</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">Profile</span><span class="o">&gt;</span> <span class="n">profiles</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">mContext</span> <span class="o">=</span> <span class="n">context</span><span class="o">;</span>
        <span class="n">mProfiles</span> <span class="o">=</span> <span class="n">profiles</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">MyViewHolder</span> <span class="nf">onCreateViewHolder</span><span class="o">(</span><span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">,</span> <span class="kt">int</span> <span class="n">viewType</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">final</span> <span class="n">View</span> <span class="n">itemView</span> <span class="o">=</span> <span class="n">View</span><span class="o">.</span><span class="na">inflate</span><span class="o">(</span><span class="n">mContext</span><span class="o">,</span> <span class="n">R</span><span class="o">.</span><span class="na">layout</span><span class="o">.</span><span class="na">list_item</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">MyViewHolder</span><span class="o">(</span><span class="n">itemView</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onBindViewHolder</span><span class="o">(</span><span class="n">MyViewHolder</span> <span class="n">holder</span><span class="o">,</span> <span class="kt">int</span> <span class="n">position</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">final</span> <span class="n">Profile</span> <span class="n">profile</span> <span class="o">=</span> <span class="n">mProfiles</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">position</span><span class="o">);</span>
        <span class="n">holder</span><span class="o">.</span><span class="na">name</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
        <span class="n">holder</span><span class="o">.</span><span class="na">bio</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getBio</span><span class="o">());</span>
        <span class="n">holder</span><span class="o">.</span><span class="na">img</span><span class="o">.</span><span class="na">setImageResource</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getProfileImageResource</span><span class="o">());</span>
    <span class="o">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">getItemCount</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">mProfiles</span><span class="o">.</span><span class="na">size</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">class</span> <span class="nc">MyViewHolder</span> <span class="kd">extends</span> <span class="n">RecyclerView</span><span class="o">.</span><span class="na">ViewHolder</span> <span class="o">{</span>
        <span class="n">TextView</span> <span class="n">name</span><span class="o">;</span>
        <span class="n">TextView</span> <span class="n">bio</span><span class="o">;</span>
        <span class="n">ImageView</span> <span class="n">img</span><span class="o">;</span>

        <span class="n">MyViewHolder</span><span class="o">(</span><span class="n">View</span> <span class="n">itemView</span><span class="o">)</span> <span class="o">{</span>
            <span class="kd">super</span><span class="o">(</span><span class="n">itemView</span><span class="o">);</span>
            <span class="n">name</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">itemView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_name</span><span class="o">);</span>
            <span class="n">bio</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">itemView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_bio</span><span class="o">);</span>
            <span class="n">img</span> <span class="o">=</span> <span class="o">(</span><span class="n">ImageView</span><span class="o">)</span> <span class="n">itemView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">iv_profile_image</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</pre></div>
<hr>

<h1 id="want-to-support-this-kind-of-content-buy-rany-a-coffee">Want to support this kind of content ? <a href="https://ko-fi.com/E1E0B4X4">Buy Rany a Coffee</a></h1>
]]></content:encoded>
      </item>
      <item>
        <guid>https://ranyalbegwein.silvrback.com/listview-and-viewholder#28543</guid>
          <pubDate>Fri, 25 Nov 2016 01:08:00 +0200</pubDate>
        <link>https://ranyalbegwein.silvrback.com/listview-and-viewholder</link>
        <title>ListView and ViewHolder</title>
        <description>Enhance ListView&#39;s performance to reduce strain from the UI thread</description>
        <content:encoded><![CDATA[<p>One of the main concerns an Android developer should have is reducing strain from the main thread, also known as the UI thread.</p>

<p><strong>ListView</strong> is one of the most common views in Android and it is important to know how to write a fast adapter for it. One of the ways to enahnce your <strong>ListView</strong> performance is by using a <strong>ViewHolder</strong> pattern.</p>

<p>Assume we have an object named <strong>Profile</strong> which describes some basic information of a person. It has an image, a name and a short bio.</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Profile</span> <span class="o">{</span>
    <span class="cm">/**</span>
<span class="cm">     * Name of person.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">mName</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * Bio.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">String</span> <span class="n">mBio</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * Profile image resource.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">mProfileImageResource</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">Profile</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">String</span> <span class="n">bio</span><span class="o">,</span> <span class="kt">int</span> <span class="n">profileImageResource</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">mName</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
        <span class="n">mBio</span> <span class="o">=</span> <span class="n">bio</span><span class="o">;</span>
        <span class="n">mProfileImageResource</span> <span class="o">=</span> <span class="n">profileImageResource</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="cm">/* &quot;Get&quot; methods... */</span>
<span class="o">}</span>
</pre></div>
<p>We would also want to create a <strong>ListView</strong> of <strong>Profile</strong>s, in which every row looks like this:</p>

<p><img alt="Silvrback blog image" src="https://silvrback.s3.amazonaws.com/uploads/0258f510-45bd-43fa-9e08-1ee6ff828bbb/smooth_listview_rowview_image_large.jpg" /></p>

<p>and can be described in XML ( <code>R.layout.list_item</code> ) like this:</p>
<div class="highlight"><pre><span></span><span class="nt">&lt;RelativeLayout</span> <span class="na">xmlns:android=</span><span class="s">&quot;http://schemas.android.com/apk/res/android&quot;</span>
                <span class="na">android:layout_width=</span><span class="s">&quot;match_parent&quot;</span>
                <span class="na">android:layout_height=</span><span class="s">&quot;match_parent&quot;</span><span class="nt">&gt;</span>

    <span class="nt">&lt;ImageView</span>
        <span class="na">android:id=</span><span class="s">&quot;@+id/iv_profile_image&quot;</span>
        <span class="na">android:layout_width=</span><span class="s">&quot;50dp&quot;</span>
        <span class="na">android:layout_height=</span><span class="s">&quot;50dp&quot;</span>
        <span class="na">android:layout_alignParentStart=</span><span class="s">&quot;true&quot;</span>
        <span class="na">android:layout_alignParentTop=</span><span class="s">&quot;true&quot;</span><span class="nt">/&gt;</span>

    <span class="nt">&lt;TextView</span>
        <span class="na">android:id=</span><span class="s">&quot;@+id/tv_name&quot;</span>
        <span class="na">android:layout_width=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_height=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_above=</span><span class="s">&quot;@+id/tv_bio&quot;</span>
        <span class="na">android:layout_alignParentEnd=</span><span class="s">&quot;true&quot;</span>
        <span class="na">android:layout_alignParentTop=</span><span class="s">&quot;true&quot;</span>
        <span class="na">android:layout_toEndOf=</span><span class="s">&quot;@+id/iv_profile_image&quot;</span>
        <span class="na">android:padding=</span><span class="s">&quot;@dimen/padding_profile_text&quot;</span><span class="nt">/&gt;</span>

    <span class="nt">&lt;TextView</span>
        <span class="na">android:id=</span><span class="s">&quot;@+id/tv_bio&quot;</span>
        <span class="na">android:layout_width=</span><span class="s">&quot;match_parent&quot;</span>
        <span class="na">android:layout_height=</span><span class="s">&quot;wrap_content&quot;</span>
        <span class="na">android:layout_alignBottom=</span><span class="s">&quot;@+id/iv_profile_image&quot;</span>
        <span class="na">android:layout_toEndOf=</span><span class="s">&quot;@+id/iv_profile_image&quot;</span>
        <span class="na">android:paddingLeft=</span><span class="s">&quot;@dimen/padding_profile_text&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/RelativeLayout&gt;</span>
</pre></div>
<p>To start, we should write an adapter ( <strong>ArrayAdapter</strong>&lt;<strong>Profile</strong>&gt; for the sake of an example ) which should look something like this:</p>
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyArrayAdapter</span> <span class="kd">extends</span> <span class="n">ArrayAdapter</span><span class="o">&lt;</span><span class="n">Profile</span><span class="o">&gt;</span> <span class="o">{</span>

    <span class="kd">private</span> <span class="n">Context</span> <span class="n">mContext</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * A layout inflater to create Views from XML.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">LayoutInflater</span> <span class="n">mInflater</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * Row View resource.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">mResource</span><span class="o">;</span>
    <span class="cm">/**</span>
<span class="cm">     * List of profiles.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">Profile</span><span class="o">&gt;</span> <span class="n">mProfiles</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">MyArrayAdapter</span><span class="o">(</span><span class="n">Context</span> <span class="n">context</span><span class="o">,</span> <span class="kt">int</span> <span class="n">resource</span><span class="o">,</span> <span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">Profile</span><span class="o">&gt;</span> <span class="n">list</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">(</span><span class="n">context</span><span class="o">,</span> <span class="n">resource</span><span class="o">,</span> <span class="n">list</span><span class="o">);</span>

        <span class="n">mContext</span> <span class="o">=</span> <span class="n">context</span><span class="o">;</span>
        <span class="n">mResource</span> <span class="o">=</span> <span class="n">resource</span><span class="o">;</span>
        <span class="n">mProfiles</span> <span class="o">=</span> <span class="n">list</span><span class="o">;</span>

        <span class="n">mInflater</span> <span class="o">=</span> <span class="n">LayoutInflater</span><span class="o">.</span><span class="na">from</span><span class="o">(</span><span class="n">mContext</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@NonNull</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">View</span> <span class="nf">getView</span><span class="o">(</span><span class="kt">int</span> <span class="n">position</span><span class="o">,</span> <span class="n">View</span> <span class="n">convertView</span><span class="o">,</span> <span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>
        <span class="cm">/**</span>
<span class="cm">         * Missing implementation.</span>
<span class="cm">         */</span>
    <span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p><code>getView()</code> is the main method we should focus on here, as it&#39;s the method which gets called by the system every time a new <strong>View</strong> needs to be inflated, updated and returned - to display the data ( a <strong>Profile</strong> ) at the specified position in the data set ( <strong>Profile</strong>s list in our case ).</p>

<p>Let&#39;s consider the following <code>getView()</code>:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@NonNull</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">View</span> <span class="nf">getView</span><span class="o">(</span><span class="kt">int</span> <span class="n">position</span><span class="o">,</span> <span class="n">View</span> <span class="n">convertView</span><span class="o">,</span> <span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>

        <span class="cm">/**</span>
<span class="cm">         * 1. Inflating layout from resource.</span>
<span class="cm">         */</span>
        <span class="kd">final</span> <span class="n">View</span> <span class="n">rowView</span> <span class="o">=</span> <span class="n">mInflater</span><span class="o">.</span><span class="na">inflate</span><span class="o">(</span><span class="n">mResource</span><span class="o">,</span> <span class="n">parent</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>

        <span class="cm">/**</span>
<span class="cm">         * 2. Finding views by id.</span>
<span class="cm">         */</span>
        <span class="n">TextView</span> <span class="n">name</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">rowView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_name</span><span class="o">);</span>
        <span class="n">TextView</span> <span class="n">bio</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">rowView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_bio</span><span class="o">);</span>
        <span class="n">ImageView</span> <span class="n">img</span> <span class="o">=</span> <span class="o">(</span><span class="n">ImageView</span><span class="o">)</span> <span class="n">rowView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">iv_profile_image</span><span class="o">);</span>

        <span class="n">Profile</span> <span class="n">profile</span> <span class="o">=</span> <span class="n">mProfiles</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">position</span><span class="o">);</span>

        <span class="cm">/**</span>
<span class="cm">         * Setting information.</span>
<span class="cm">         */</span>
        <span class="n">name</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
        <span class="n">bio</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getBio</span><span class="o">());</span>
        <span class="n">img</span><span class="o">.</span><span class="na">setImageResource</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getProfileImageResource</span><span class="o">());</span>

        <span class="k">return</span> <span class="n">rowView</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div>
<p>Very slow!</p>

<p>As the <strong>ListView</strong> is being scrolled and <code>getView()</code> is called, two tasks happen:</p>

<ul>
<li><code>R.layout.list_item</code> is inflated into a new <strong>View</strong>.</li>
<li>A series of  <code>findViewById()</code> calls are executed, one call for each inner <strong>View</strong> in our layout.</li>
</ul>

<p>Getting called frequently, these two tasks are very performance-expensive, especially if  <code>R.layout.list_item</code> is large and more complex.</p>

<h2 id="1-using-listviews-recycling-mechanism">1. Using ListView&#39;s recycling mechanism</h2>

<p>To take care of the first task and avoid inflating the same <strong>View</strong> over and over again, we can take advantage of <strong>ListView</strong>&#39;s inner recycling mechanism. <strong>ListView</strong> works with a <code>RecycleBin</code> object ; a data set used to store unused views that should be reused during the next layout to avoid creating new ones.</p>

<p>Sounds great! How do we know when a <strong>View</strong> is being recycled ? By the value of  <code>convertView</code> argument we get in <code>getView(int position, View convertView, ViewGroup parent)</code>&#39;s second parameter.</p>

<p>When <code>convertView</code> is <strong><em>not null</em></strong>, the system actually tells us : &quot;<em>There you go, an already inflated View which is currently not visible to the user and which you can use to update its contents according to your data set and position, instead of inflating a new one.</em>&quot;</p>

<p>Therefore, we can update our <code>getView()</code> code to effectively use this recycling behavior:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@NonNull</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">View</span> <span class="nf">getView</span><span class="o">(</span><span class="kt">int</span> <span class="n">position</span><span class="o">,</span> <span class="n">View</span> <span class="n">convertView</span><span class="o">,</span> <span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>

        <span class="cm">/**</span>
<span class="cm">         * 1. Inflating layout from resource.</span>
<span class="cm">         */</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">convertView</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">convertView</span> <span class="o">=</span> <span class="n">mInflater</span><span class="o">.</span><span class="na">inflate</span><span class="o">(</span><span class="n">mResource</span><span class="o">,</span> <span class="n">parent</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="cm">/**</span>
<span class="cm">         * 2. Finding views by id.</span>
<span class="cm">         */</span>
        <span class="n">TextView</span> <span class="n">name</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_name</span><span class="o">);</span>
        <span class="n">TextView</span> <span class="n">bio</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_bio</span><span class="o">);</span>
        <span class="n">ImageView</span> <span class="n">img</span> <span class="o">=</span> <span class="o">(</span><span class="n">ImageView</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">iv_profile_image</span><span class="o">);</span>

        <span class="n">Profile</span> <span class="n">profile</span> <span class="o">=</span> <span class="n">mProfiles</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">position</span><span class="o">);</span>

        <span class="cm">/**</span>
<span class="cm">         * Setting information.</span>
<span class="cm">         */</span>
        <span class="n">name</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
        <span class="n">bio</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getBio</span><span class="o">());</span>
        <span class="n">img</span><span class="o">.</span><span class="na">setImageResource</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getProfileImageResource</span><span class="o">());</span>

        <span class="k">return</span> <span class="n">convertView</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div>
<p>Faster! But not enough.</p>

<h2 id="2-the-viewholder-pattern">2. The ViewHolder pattern</h2>

<p>To take care of the second task, and reduce the amount of <code>findViewById()</code> calls, a <strong>ViewHolder</strong> pattern takes place.<br>
As you can quite easily guess, A <strong>ViewHolder</strong> is an object whose only purpose is to <em>hold</em>      references and give access to our layout&#39;s inner <strong>View</strong>s.</p>

<p>The <strong>ViewHolder</strong> will hold the returning <strong>View</strong>s from <code>findViewById()</code> calls and will be kept as a <em>tag</em> object inside <code>convertView</code> for later retrieval and usage.</p>

<p>Our <strong>ViewHolder</strong> looks like this:</p>
<div class="highlight"><pre><span></span>    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">ViewHolder</span> <span class="o">{</span>
        <span class="n">TextView</span> <span class="n">name</span><span class="o">;</span>
        <span class="n">TextView</span> <span class="n">bio</span><span class="o">;</span>
        <span class="n">ImageView</span> <span class="n">img</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div>
<p>Let&#39;s use it to update <code>getView()</code> and enhance our <strong>ListView</strong> performance even further:</p>
<div class="highlight"><pre><span></span>    <span class="nd">@NonNull</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">View</span> <span class="nf">getView</span><span class="o">(</span><span class="kt">int</span> <span class="n">position</span><span class="o">,</span> <span class="n">View</span> <span class="n">convertView</span><span class="o">,</span> <span class="n">ViewGroup</span> <span class="n">parent</span><span class="o">)</span> <span class="o">{</span>

        <span class="n">ViewHolder</span> <span class="n">vh</span><span class="o">;</span>
        <span class="cm">/**</span>
<span class="cm">         * 1. Inflating layout from resource.</span>
<span class="cm">         */</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">convertView</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">convertView</span> <span class="o">=</span>  <span class="n">mInflater</span><span class="o">.</span><span class="na">inflate</span><span class="o">(</span><span class="n">mResource</span><span class="o">,</span> <span class="n">parent</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>

            <span class="n">vh</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ViewHolder</span><span class="o">();</span>
            <span class="cm">/**</span>
<span class="cm">             * 2. Finding views by id.</span>
<span class="cm">             */</span>
            <span class="n">vh</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_name</span><span class="o">);</span>
            <span class="n">vh</span><span class="o">.</span><span class="na">bio</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">tv_bio</span><span class="o">);</span>
            <span class="n">vh</span><span class="o">.</span><span class="na">img</span> <span class="o">=</span> <span class="o">(</span><span class="n">ImageView</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">iv_profile_image</span><span class="o">);</span>

            <span class="cm">/**</span>
<span class="cm">             * Keep the ViewHolder as a tag for later retrieval and usage.</span>
<span class="cm">             */</span>
            <span class="n">convertView</span><span class="o">.</span><span class="na">setTag</span><span class="o">(</span><span class="n">vh</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
            <span class="cm">/**</span>
<span class="cm">             * Grab the already stored ViewHolder to save findViewById() calls.</span>
<span class="cm">             */</span>
            <span class="n">vh</span> <span class="o">=</span> <span class="o">(</span><span class="n">ViewHolder</span><span class="o">)</span> <span class="n">convertView</span><span class="o">.</span><span class="na">getTag</span><span class="o">();</span>
        <span class="o">}</span>

        <span class="n">Profile</span> <span class="n">profile</span> <span class="o">=</span> <span class="n">mProfiles</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">position</span><span class="o">);</span>

        <span class="cm">/**</span>
<span class="cm">         * Setting information.</span>
<span class="cm">         * This time - using our already set ViewHolder.</span>
<span class="cm">         */</span>
        <span class="n">vh</span><span class="o">.</span><span class="na">name</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
        <span class="n">vh</span><span class="o">.</span><span class="na">bio</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getBio</span><span class="o">());</span>
        <span class="n">vh</span><span class="o">.</span><span class="na">img</span><span class="o">.</span><span class="na">setImageResource</span><span class="o">(</span><span class="n">profile</span><span class="o">.</span><span class="na">getProfileImageResource</span><span class="o">());</span>

        <span class="k">return</span> <span class="n">convertView</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">ViewHolder</span> <span class="o">{</span>
        <span class="n">TextView</span> <span class="n">name</span><span class="o">;</span>
        <span class="n">TextView</span> <span class="n">bio</span><span class="o">;</span>
        <span class="n">ImageView</span> <span class="n">img</span><span class="o">;</span>
    <span class="o">}</span>
</pre></div>
<p>Extremely faster!</p>

<p>As you can see, when <code>convertView</code> is null, we do not only inflate a new <strong>View</strong> but also create a new <strong>ViewHolder</strong>. This <strong>ViewHolder</strong> holds references to <strong>View</strong>s returned from the calls to <code>findViewById()</code>. We use the function <code>View#setTag(Object)</code> to save the populated <strong>ViewHolder</strong> inside <code>convertView</code>, so that when we get a <strong><em>not null</em></strong> <code>convertView</code> in one of the next calls to <code>getView()</code>, we&#39;ll be able to retrieve it back via <code>View#getTag()</code>, skip the calls to <code>findViewById()</code> and save time !</p>

<hr>

<h1 id="want-to-support-this-kind-of-content-buy-rany-a-coffee">Want to support this kind of content ? <a href="https://ko-fi.com/E1E0B4X4">Buy Rany a Coffee</a></h1>
]]></content:encoded>
      </item>
  </channel>
</rss>