{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Kyle Mallette",
  "description": "A blog about programming the web and Android",
  "home_page_url": "https://www.kylemallette.com/",
  "feed_url": "https://www.kylemallette.com/feed.json",
  "language": "en",
  "authors": [{
    "name": "Kyle Mallette",
    "url": "https://www.kylemallette.com/about/",
    "avatar": "https://www.kylemallette.com/images/me.jpg"
  }],
  "items": [
    {
      "id": "https://www.kylemallette.com/android/2013/09/16/refreshing-lists-part2.html",
      "url": "https://www.kylemallette.com/android/2013/09/16/refreshing-lists-part2.html",
      "title": "Refreshing ExpandableListView",
      "summary": "Refreshing visible ExpandableListView items: flat list, packed, group, and child positions, and how ExpandableListConnector maps between them.",
      "content_html": "<p>Refreshing visible ExpandableListView items has some extra steps and concerns. A quick glance at <a href=\"http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/ExpandableListView.java#ExpandableListView\">ExpandableListView’s source</a> shows that relatively few inherited methods are overridden. Instead, <a href=\"http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/ExpandableListConnector.java\" title=\"ExpandableListConnector source code\">ExpandableListConnector</a> does the heavy lifting for ExpandableListView’s extra functionality.</p>\n\n<p>Internally, this connector translates the flat list position that the ListAdapter expects to/from group and child positions that the ExpandableListAdapter expects.</p>\n\n<p>If you browse the whole file, you’ll find some TODOs and get the feeling that the Android team probably didn’t get to spend as much time as they may have wanted on this widget. Thankfully, they’ve provided us some convenience methods to translate positions in a mostly straightforward manner which gives us access to some of ListView’s functionality directly.</p>\n\n<h2 id=\"do-you-mean-position-position-or-position\">Do you mean position, position or position?</h2>\n\n<p>As the heading hints at, ExpandableListView and ListView have different terminology to differentiate which type of position is being used. Inside the ExpandableListConnector source, some helpful implementation notes were left for us defining three types of positions. Along with the published ExpandableListView docs, we get a decent picture of the four position types we’ll be using. I imagine you’re already familiar with group and child positions, but I’ve listed them for completeness anyway.</p>\n\n<dl class=\"dl-horizontal\">\n  <dt>\n  Flat list position:\n  </dt>\n  <dd>\n    The position used by ListView and its adapters\n  </dd>\n\n  <dt>\n    Packed position:\n  </dt>\n  <dd>\n    A long that \"packs\" (bit twiddling) what type of position (group, child, or null for headers/footers) as well as the position value(s) (group/child values)\n  </dd>\n\n  <dt>\n    Group position:\n  </dt>\n  <dd>\n    The position of a group among all the groups used by ExpandableListView and its adapters.\n  </dd>\n\n  <dt>\n    Child position:\n  </dt>\n  <dd>\n    The position of a child among all the children in a group used by ExpandableListView and its adapters\n  </dd>\n</dl>\n\n<p><em>Note: We’re going to be dealing with 5 different kinds of positions for our color refresh example. The other type if you recall from the previous ListView color refresh example, is the ViewGroup position we used with <code class=\"language-plaintext highlighter-rouge\">getChildAt(int position)</code>.</em></p>\n\n<p>Two methods allow us to convert flat list positions to packed positions and vice versa:</p>\n\n<p><br /></p>\n\n<table class=\"table-striped table-responsive\">\n  <thead>\n    <tr><th>Public Methods</th></tr>\n  </thead>\n  <tr>\n    <td>long</td><td><a href=\" http://developer.android.com/reference/android/widget/ExpandableListView.html#getExpandableListPosition(int)\" title=\"getExpandableListPosition Documentation\">getExpandableListPosition(int flatListPosition)</a><br />\n                      Converts a flat list position (the raw position of an item (child or group) in the list) to a group and/or child position (represented in a packed position). This is useful in situations where the caller needs to use the underlying ListView's methods.\n                  </td>\n                    </tr>\n\n    <tr><td>int</td><td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#getFlatListPosition(long)\" tittle=\"getFlatListPosition Documentation\">getFlatListPosition(long packedPosition)</a><br />\n                        Reverses the conversion from a packed position to a flat list position.\n                    </td></tr>\n</table>\n\n<p><br /></p>\n\n<p>Finally, five static methods allow us to pack group/child positions and unpack packed positions. These first three take a packed position and return which type of ExpandableListView (group and child positions) position it is and the position value(s). Note that for a <code class=\"language-plaintext highlighter-rouge\">PACKED_POSITION_TYPE_CHILD</code> both group and child position values are packed up.</p>\n\n<p><br /></p>\n\n<table class=\"table-striped table-responsive\">\n   <thead>\n    <tr><th>Public Methods</th></tr>\n  </thead>\n  <tr>\n    <td>static int</td><td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#getPackedPositionGroup(long)\" title=\"getPackedPositionGroup Documentation\">getPackedPositionGroup(long packedPosition)</a><br />\n                            Gets the group position from a packed position.</td>\n  </tr>\n  <tr>\n    <td>static int</td><td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#getPackedPositionChild(long)\" title=\"getPackedPositionChild Documentation\"> getPackedPositionChild(long packedPosition)</a><br />\n                            Gets the child position from a packed position that is of `PACKED_POSITION_TYPE_CHILD` type. </td>\n  </tr>\n  <tr>\n    <td>static int</td><td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#getPackedPositionType(long)\" title=\"getPackedPositionType Documentation\">getPackedPositionType(long packedPosition)</a><br />\n                           Gets the type of a packed position.</td>\n  </tr>\n  <tr>\n    <td>static long</td><td><a href=\" http://developer.android.com/reference/android/widget/ExpandableListView.html#getPackedPositionForChild(int, int)\" title=\"getPackedPositionForChild Documentation\">getPackedPositionForChild(int groupPosition, int childPosition)</a><br />\n                           Returns the packed position representation of a child's position.</td>\n  </tr>\n  <tr>\n    <td>static long</td><td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#getPackedPositionForGroup(int)\" title=\"getPackedPositionForGroup Documentation\">getPackedPositionForGroup(int groupPosition)</a><br />\n\n        Returns the packed position representation of a group's position.</td>\n  </tr>\n</table>\n\n<p><br /></p>\n\n<p>Possible packed position types are:</p>\n\n<p><br /></p>\n\n<table class=\"table-striped table-responsive\">\n  <thead>\n     <thead>\n    <tr><th>Constants</th></tr>\n  </thead>\n  </thead>\n  <tr>\n    <td>int</td>\n    <td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#PACKED_POSITION_TYPE_CHILD\" title=\"PACKED_POSITION_TYPE_CHILD Documentation\">PACKED_POSITION_TYPE_CHILD </a></td>\n    <td>The packed position represents a child.</td>\n  </tr>\n  <tr>\n    <td>int</td>\n    <td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#PACKED_POSITION_TYPE_GROUP\" title=\"PACKED_POSITION_TYPE_GROUP Documentation\">PACKED_POSITION_TYPE_GROUP</a></td>\n    <td>The packed position represents a group.</td>\n  </tr>\n  <tr>\n    <td>int</td>\n    <td><a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html#PACKED_POSITION_TYPE_NULL\" title=\"PACKED_POSITION_TYPE_NULL Documentation\">PACKED_POSITION_TYPE_NULL</a></td>\n    <td>The packed position represents a neither/null/no preference.</td>\n  </tr>\n</table>\n\n<p><br /></p>\n\n<p>Here’s a quick code snippet to illustrate the conversion flow:</p>\n\n<figure class=\"highlight\"><pre><code class=\"language-java\" data-lang=\"java\"><span class=\"cm\">/*  FlatList position  -&gt;  Packed position  -&gt;  ExpandableList Group/Child positions\n *           ^                    ^                              ^    ^\n *        integer                long                           integers\n */</span>\n\n  <span class=\"c1\">// 1. Flat list position  -&gt;  Packed position</span>\n  <span class=\"kt\">long</span> <span class=\"n\">packedPosition</span> <span class=\"o\">=</span> <span class=\"n\">getExpandableListPosition</span><span class=\"o\">(</span><span class=\"n\">flatListPosition</span><span class=\"o\">);</span>\n\n  <span class=\"c1\">// 2. Unpack packed position type</span>\n  <span class=\"kt\">int</span> <span class=\"n\">positionType</span> <span class=\"o\">=</span> <span class=\"n\">getPackedPositionType</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span>\n\n  <span class=\"c1\">// 3. Unpack position values based on positionType</span>\n  <span class=\"c1\">//    if not PACKED_POSITION_TYPE_NULL there will at least be a groupPosition</span>\n  <span class=\"k\">if</span><span class=\"o\">(</span> <span class=\"n\">positionType</span> <span class=\"o\">!=</span> <span class=\"no\">PACKED_POSITION_TYPE_NULL</span> <span class=\"o\">){</span>\n\n      <span class=\"n\">groupPosition</span> <span class=\"o\">=</span> <span class=\"n\">getPackedPositionGroup</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span>\n\n      <span class=\"k\">if</span><span class=\"o\">(</span><span class=\"n\">positionType</span> <span class=\"o\">==</span> <span class=\"no\">PACKED_POSITION_TYPE_CHILD</span><span class=\"o\">){</span>\n          <span class=\"n\">childPosition</span> <span class=\"o\">=</span> <span class=\"n\">getPackedPositionChild</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span>\n      <span class=\"o\">}</span>\n\n  <span class=\"o\">}</span><span class=\"k\">else</span><span class=\"o\">{</span>\n      <span class=\"nc\">Log</span><span class=\"o\">.</span><span class=\"na\">d</span><span class=\"o\">(</span><span class=\"s\">\"FooLabel\"</span><span class=\"o\">,</span> <span class=\"s\">\"positionType was NULL - header/footer?\"</span><span class=\"o\">);</span>\n  <span class=\"o\">}</span></code></pre></figure>\n\n<p>The reverse is a breeze.</p>\n\n<figure class=\"highlight\"><pre><code class=\"language-java\" data-lang=\"java\"> <span class=\"cm\">/*  To Convert from an ExpandableList position to a packed position there's\n  *  only two steps.\n  *    1. Pack up our ExpandableList position. Two methods are available to pack\n  *       up the two kinds of ExpandableList positions; group and child.\n  *    2. Convert from a packed position to a flat list position\n  */</span>\n <span class=\"kt\">long</span> <span class=\"n\">packedPosition</span> <span class=\"o\">=</span>\n         <span class=\"n\">getPackedPositionForGroup</span><span class=\"o\">(</span><span class=\"n\">groupPosition</span><span class=\"o\">);</span> <span class=\"c1\">//For a group position</span>\n         <span class=\"n\">getPackedPositionForChild</span><span class=\"o\">(</span><span class=\"n\">groupPosition</span><span class=\"o\">,</span> <span class=\"n\">childPosition</span><span class=\"o\">);</span> <span class=\"c1\">//For a child position</span>\n\n <span class=\"c1\">// Can now use this to access ListView functionality directly</span>\n <span class=\"kt\">int</span> <span class=\"n\">flatListPosition</span> <span class=\"o\">=</span> <span class=\"n\">getFlatListPosition</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span></code></pre></figure>\n\n<h2 id=\"now-can-we-refresh-visible-items\">Now Can We Refresh Visible Items?</h2>\n<p>Yes! Now that the various positions values make sense, let’s implement our color refresh example.</p>\n\n<figure class=\"highlight\"><pre><code class=\"language-java\" data-lang=\"java\"><span class=\"c1\">// Declare the initial list item colors</span>\n<span class=\"kd\">private</span> <span class=\"kt\">int</span>             <span class=\"n\">groupTextColor</span>  <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">BLACK</span><span class=\"o\">;</span>\n<span class=\"kd\">private</span> <span class=\"kt\">int</span>             <span class=\"n\">childTextColor</span>  <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">BLACK</span><span class=\"o\">;</span>\n<span class=\"kd\">private</span> <span class=\"kt\">int</span>             <span class=\"n\">childBgColor</span>  <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">WHITE</span><span class=\"o\">;</span>\n<span class=\"kd\">private</span> <span class=\"kt\">int</span>             <span class=\"n\">groupBgColor</span>  <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">WHITE</span><span class=\"o\">;</span>\n\n<span class=\"cm\">/*  Grabs the user color inputs and converts them proper integer color values.\n *  Since we're working on an ExpandableListView, we'll need four inputs for\n *  group and child text colors as well as group and child background colors.\n *\n *  Definitely check out Color.parseColor(String). It's very handy!\n */</span>\n<span class=\"kd\">private</span> <span class=\"kt\">void</span> <span class=\"nf\">retrieveColors</span><span class=\"o\">()</span> <span class=\"o\">{</span>\n\n    <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mGroupTextColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">().</span><span class=\"na\">length</span><span class=\"o\">()</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"o\">)</span>\n      <span class=\"n\">groupTextColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">parseColor</span><span class=\"o\">(</span><span class=\"n\">mGroupTextColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">()</span>\n                                                            <span class=\"o\">.</span><span class=\"na\">toString</span><span class=\"o\">()</span>\n                                                            <span class=\"o\">.</span><span class=\"na\">toLowerCase</span><span class=\"o\">());</span>\n    <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mChildTextColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">().</span><span class=\"na\">length</span><span class=\"o\">()</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"o\">)</span>\n          <span class=\"n\">childTextColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">parseColor</span><span class=\"o\">(</span><span class=\"n\">mChildTextColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">()</span>\n                                                                <span class=\"o\">.</span><span class=\"na\">toString</span><span class=\"o\">()</span>\n                                                                <span class=\"o\">.</span><span class=\"na\">toLowerCase</span><span class=\"o\">());</span>\n    <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mChildBackgroundColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">().</span><span class=\"na\">length</span><span class=\"o\">()</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"o\">)</span>\n      <span class=\"n\">childBgColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">parseColor</span><span class=\"o\">(</span><span class=\"n\">mChildBackgroundColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">()</span>\n                                                                <span class=\"o\">.</span><span class=\"na\">toString</span><span class=\"o\">()</span>\n                                                                <span class=\"o\">.</span><span class=\"na\">toLowerCase</span><span class=\"o\">());</span>\n    <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mGroupBackgroundColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">().</span><span class=\"na\">length</span><span class=\"o\">()</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"o\">)</span>\n      <span class=\"n\">groupBgColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">parseColor</span><span class=\"o\">(</span><span class=\"n\">mGroupBackgroundColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">()</span>\n                                                                <span class=\"o\">.</span><span class=\"na\">toString</span><span class=\"o\">()</span>\n                                                                <span class=\"o\">.</span><span class=\"na\">toLowerCase</span><span class=\"o\">());</span>\n<span class=\"o\">}</span>\n\n<span class=\"cm\">/*  Applies the user supplied color values to the visible list items. This\n *  does not touch the recycled off screen views.*/</span>\n<span class=\"kd\">private</span> <span class=\"kt\">void</span> <span class=\"nf\">applyColors</span><span class=\"o\">(){</span>\n\n  <span class=\"nc\">View</span> <span class=\"n\">listItem</span><span class=\"o\">;</span>\n  <span class=\"nc\">ViewHolder</span> <span class=\"n\">mHolder</span><span class=\"o\">;</span>\n\n  <span class=\"n\">retrieveColors</span><span class=\"o\">();</span>\n\n  <span class=\"kt\">int</span> <span class=\"n\">packedPositionType</span><span class=\"o\">,</span> <span class=\"n\">groupPosition</span><span class=\"o\">,</span> <span class=\"n\">childPosition</span><span class=\"o\">;</span>\n\n  <span class=\"c1\">// These are both implemented in AdapterView which means</span>\n  <span class=\"c1\">// they're flat list positions</span>\n  <span class=\"kt\">int</span> <span class=\"n\">firstVis</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getFirstVisiblePosition</span><span class=\"o\">();</span>\n  <span class=\"kt\">int</span> <span class=\"n\">lastVis</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getLastVisiblePosition</span><span class=\"o\">();</span>\n\n  <span class=\"cm\">/* This is the \"conversion\" from flat list positions to ViewGroup child positions */</span>\n  <span class=\"kt\">int</span> <span class=\"n\">count</span> <span class=\"o\">=</span> <span class=\"n\">lastVis</span> <span class=\"o\">-</span> <span class=\"n\">firstVis</span><span class=\"o\">;</span>\n\n  <span class=\"kt\">long</span> <span class=\"n\">packedPosition</span><span class=\"o\">;</span>\n\n  <span class=\"k\">while</span> <span class=\"o\">(</span><span class=\"n\">count</span> <span class=\"o\">&gt;=</span> <span class=\"mi\">0</span><span class=\"o\">){</span> <span class=\"c1\">// looping through visible list items</span>\n\n    <span class=\"cm\">/*  getChildAt(pos) is implemented in ViewGroup and has a different meaning for\n     *  its position values. ViewGroup tracks visible items as children and is 0 indexed.\n     *  This means you'll have 0 - X positions where X is however many items it takes\n     *  to fill the visible area of your screen; usually less than 10. */</span>\n    <span class=\"n\">listItem</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getChildAt</span><span class=\"o\">(</span><span class=\"n\">count</span><span class=\"o\">);</span>\n\n    <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">listItem</span> <span class=\"o\">!=</span> <span class=\"kc\">null</span><span class=\"o\">){</span>\n\n      <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">ViewHolder</span><span class=\"o\">)</span> <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">getTag</span><span class=\"o\">();</span>\n      <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mHolder</span> <span class=\"o\">==</span> <span class=\"kc\">null</span><span class=\"o\">){</span> <span class=\"c1\">// This shouldn't happen, but we'll make</span>\n                            <span class=\"c1\">// sure in case some strange concurrency</span>\n                            <span class=\"c1\">// bugs appear</span>\n        <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"k\">new</span> <span class=\"nc\">ViewHolder</span><span class=\"o\">();</span>\n        <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">TextView</span><span class=\"o\">)</span> <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">findViewById</span><span class=\"o\">(</span><span class=\"n\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">id</span><span class=\"o\">.</span><span class=\"na\">text1</span><span class=\"o\">);</span>\n        <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">setTag</span><span class=\"o\">(</span><span class=\"n\">mHolder</span><span class=\"o\">);</span>\n      <span class=\"o\">}</span>\n\n      <span class=\"cm\">/*  Adding count, which is our current ViewGroup visible item position to\n       *  AdapterView's firstVisiblePosition which is a flat list position gives us\n       *  our current flat list position. From that we'll follow the flat list to\n       *  expandable list position (group/child values) flow:\n       *\n       *      FlatListPos &gt; packed position &gt; group/child position(s)\n       */</span>\n      <span class=\"n\">packedPosition</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getExpandableListPosition</span><span class=\"o\">(</span><span class=\"n\">count</span> <span class=\"o\">+</span> <span class=\"n\">firstVis</span><span class=\"o\">);</span>\n\n      <span class=\"c1\">// Using our static helpers to unpack what type of position this item represents.</span>\n      <span class=\"n\">packedPositionType</span> <span class=\"o\">=</span> <span class=\"nc\">ExpandableListView</span><span class=\"o\">.</span><span class=\"na\">getPackedPositionType</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span>\n\n      <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">packedPositionType</span> <span class=\"o\">!=</span> <span class=\"nc\">ExpandableListView</span><span class=\"o\">.</span><span class=\"na\">PACKED_POSITION_TYPE_NULL</span><span class=\"o\">){</span>\n\n        <span class=\"cm\">/* If the packedPosition type isn't NULL then we know there has to be at least\n         * a group position value. If it's a child item, we'll additionally have a\n         * child position value */</span>\n        <span class=\"n\">groupPosition</span> <span class=\"o\">=</span> <span class=\"nc\">ExpandableListView</span><span class=\"o\">.</span><span class=\"na\">getPackedPositionGroup</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span>\n\n        <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">packedPositionType</span> <span class=\"o\">==</span> <span class=\"nc\">ExpandableListView</span><span class=\"o\">.</span><span class=\"na\">PACKED_POSITION_TYPE_CHILD</span><span class=\"o\">){</span>\n\n          <span class=\"n\">childPosition</span> <span class=\"o\">=</span> <span class=\"nc\">ExpandableListView</span><span class=\"o\">.</span><span class=\"na\">getPackedPositionChild</span><span class=\"o\">(</span><span class=\"n\">packedPosition</span><span class=\"o\">);</span>\n\n          <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">setBackgroundColor</span><span class=\"o\">(</span><span class=\"n\">childBgColor</span><span class=\"o\">);</span> <span class=\"c1\">// Setting our child bgColor</span>\n          <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setTextColor</span><span class=\"o\">(</span><span class=\"n\">childTextColor</span><span class=\"o\">);</span><span class=\"c1\">// Setting our child textColor</span>\n\n        <span class=\"o\">}</span><span class=\"k\">else</span><span class=\"o\">{</span>\n\n          <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">setBackgroundColor</span><span class=\"o\">(</span><span class=\"n\">groupBgColor</span><span class=\"o\">);</span> <span class=\"c1\">// Setting our group bgColor</span>\n          <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setTextColor</span><span class=\"o\">(</span><span class=\"n\">groupTextColor</span><span class=\"o\">);</span> <span class=\"c1\">// Setting our child textColor</span>\n        <span class=\"o\">}</span>\n\n      <span class=\"o\">}</span><span class=\"k\">else</span>\n        <span class=\"nc\">Log</span><span class=\"o\">.</span><span class=\"na\">d</span><span class=\"o\">(</span>  <span class=\"no\">TAG</span><span class=\"o\">,</span>\n            <span class=\"s\">\"Packed position type was null.\"</span><span class=\"o\">);</span>\n    <span class=\"o\">}</span><span class=\"k\">else</span>\n      <span class=\"nc\">Log</span><span class=\"o\">.</span><span class=\"na\">d</span><span class=\"o\">(</span>  <span class=\"no\">TAG</span><span class=\"o\">,</span>\n          <span class=\"s\">\"getChildAt didn't retrieve a non-null view\"</span><span class=\"o\">);</span>\n    <span class=\"n\">count</span><span class=\"o\">--;</span>\n  <span class=\"o\">}</span>\n<span class=\"o\">}</span></code></pre></figure>\n\n<h2 id=\"applying-changes-to-all-items\">Applying Changes to All Items</h2>\n<p>Once again, we find that although our adapter requires a bit more work compared to its ListView siblings, the strategy is the same. I’m using one ViewHolder for both since I’m using the same layout. You could make separate Holders for group and child items if they have some big differences. It’s up to you.</p>\n\n<figure class=\"highlight\"><pre><code class=\"language-java\" data-lang=\"java\"><span class=\"nd\">@Override</span>\n<span class=\"kd\">public</span> <span class=\"nc\">View</span> <span class=\"nf\">getGroupView</span><span class=\"o\">(</span><span class=\"kt\">int</span> <span class=\"n\">groupPosition</span><span class=\"o\">,</span>\n                         <span class=\"kt\">boolean</span> <span class=\"n\">isExpanded</span><span class=\"o\">,</span>\n                         <span class=\"nc\">View</span> <span class=\"n\">convertView</span><span class=\"o\">,</span>\n                         <span class=\"nc\">ViewGroup</span> <span class=\"n\">parent</span><span class=\"o\">){</span>\n\n  <span class=\"nc\">ViewHolder</span> <span class=\"n\">mHolder</span><span class=\"o\">;</span>\n\n  <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>\n    <span class=\"n\">convertView</span> <span class=\"o\">=</span> <span class=\"n\">getLayoutInflater</span><span class=\"o\">().</span><span class=\"na\">inflate</span><span class=\"o\">(</span>\n                                      <span class=\"n\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">layout</span><span class=\"o\">.</span><span class=\"na\">simple_expandable_list_item_1</span><span class=\"o\">,</span>\n                                      <span class=\"n\">parent</span><span class=\"o\">,</span>\n                                      <span class=\"kc\">false</span><span class=\"o\">);</span>\n    <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"k\">new</span> <span class=\"nc\">ViewHolder</span><span class=\"o\">();</span>\n    <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">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\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">id</span><span class=\"o\">.</span><span class=\"na\">text1</span><span class=\"o\">);</span>\n    <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">setTag</span><span class=\"o\">(</span><span class=\"n\">mHolder</span><span class=\"o\">);</span>\n  <span class=\"o\">}</span><span class=\"k\">else</span>\n    <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">ViewHolder</span><span class=\"o\">)</span> <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">getTag</span><span class=\"o\">();</span>\n\n  <span class=\"cm\">/* Since all visible items have had their appropriate user selected\n   * colors applied, we need to make sure any of the recycler's\n   * scrapped views (which wouldn't be touched by our visible item\n   * changes) also reflect our changes. */</span>\n  <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">setBackgroundColor</span><span class=\"o\">(</span><span class=\"n\">groupBgColor</span><span class=\"o\">);</span>\n  <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setTextColor</span><span class=\"o\">(</span><span class=\"n\">groupTextColor</span><span class=\"o\">);</span>\n\n  <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setText</span><span class=\"o\">(</span><span class=\"n\">getGroup</span><span class=\"o\">(</span><span class=\"n\">groupPosition</span><span class=\"o\">).</span><span class=\"na\">toString</span><span class=\"o\">().</span><span class=\"na\">toUpperCase</span><span class=\"o\">());</span>\n\n  <span class=\"k\">return</span> <span class=\"n\">convertView</span><span class=\"o\">;</span>\n<span class=\"o\">}</span>\n\n\n<span class=\"nd\">@Override</span>\n<span class=\"kd\">public</span> <span class=\"nc\">View</span> <span class=\"nf\">getChildView</span><span class=\"o\">(</span><span class=\"kt\">int</span> <span class=\"n\">groupPosition</span><span class=\"o\">,</span>\n                         <span class=\"kt\">int</span> <span class=\"n\">childPosition</span><span class=\"o\">,</span>\n                         <span class=\"kt\">boolean</span> <span class=\"n\">isLastChild</span><span class=\"o\">,</span>\n                         <span class=\"nc\">View</span> <span class=\"n\">convertView</span><span class=\"o\">,</span>\n                         <span class=\"nc\">ViewGroup</span> <span class=\"n\">parent</span><span class=\"o\">){</span>\n\n  <span class=\"nc\">ViewHolder</span> <span class=\"n\">mHolder</span><span class=\"o\">;</span>\n\n  <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>\n    <span class=\"n\">convertView</span> <span class=\"o\">=</span> <span class=\"n\">getLayoutInflater</span><span class=\"o\">().</span><span class=\"na\">inflate</span><span class=\"o\">(</span>\n                                      <span class=\"n\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">layout</span><span class=\"o\">.</span><span class=\"na\">simple_expandable_list_item_1</span><span class=\"o\">,</span>\n                                      <span class=\"n\">parent</span><span class=\"o\">,</span>\n                                      <span class=\"kc\">false</span><span class=\"o\">);</span>\n    <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"k\">new</span> <span class=\"nc\">ViewHolder</span><span class=\"o\">();</span>\n    <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">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\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">id</span><span class=\"o\">.</span><span class=\"na\">text1</span><span class=\"o\">);</span>\n    <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">setTag</span><span class=\"o\">(</span><span class=\"n\">mHolder</span><span class=\"o\">);</span>\n  <span class=\"o\">}</span><span class=\"k\">else</span>\n    <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">ViewHolder</span><span class=\"o\">)</span> <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">getTag</span><span class=\"o\">();</span>\n\n  <span class=\"cm\">/* Since all visible items have had their appropriate user selected\n   * colors applied, we need to make sure any of the recycler's\n   * scrapped views (which wouldn't be touched by our visible item\n   * changes) that may get returned also reflect our changes. */</span>\n  <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">setBackgroundColor</span><span class=\"o\">(</span><span class=\"n\">childBgColor</span><span class=\"o\">);</span>\n  <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setTextColor</span><span class=\"o\">(</span><span class=\"n\">childTextColor</span><span class=\"o\">);</span>\n\n  <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setText</span><span class=\"o\">(</span><span class=\"n\">getChild</span><span class=\"o\">(</span><span class=\"n\">groupPosition</span><span class=\"o\">,</span> <span class=\"n\">childPosition</span><span class=\"o\">).</span><span class=\"na\">toString</span><span class=\"o\">());</span>\n\n  <span class=\"k\">return</span> <span class=\"n\">convertView</span><span class=\"o\">;</span>\n<span class=\"o\">}</span></code></pre></figure>\n\n",
      "date_published": "2013-09-16T00:00:00+00:00",
      "tags": ["Exploring Lists Series","ListView","ExpandableListView"],
      "image": "https://www.kylemallette.com/images/art/photography/st-johns-piano.jpg",
      "_markdown": { "about": "https://llmstxt.org", "url": "https://www.kylemallette.com/android/2013/09/16/refreshing-lists-part2.html.md" }
    },
    {
      "id": "https://www.kylemallette.com/android/2013/09/15/refreshing-lists-part1.html",
      "url": "https://www.kylemallette.com/android/2013/09/15/refreshing-lists-part1.html",
      "title": "Refreshing ListView",
      "summary": "Why notifyDataSetChanged() seems to do nothing, what it is actually for, and how to refresh visible ListView items without replacing the adapter.",
      "content_html": "<p>If you’re like me, you’ve encountered situations where calling <code class=\"language-plaintext highlighter-rouge\">notifyDataSetChanged()</code> on your adapter doesn’t seem to do anything. Certainly, <strong>something is happening</strong>, but that doesn’t seem to always cause your ListView or ExpandableListView to redraw on screen to reflect changes to your underlying dataset. Once again, trusty <a href=\"http://stackoverflow.com/questions/2250770/how-to-refresh-android-listview/2250849#2250849\" title=\"StackOverflow Question: How do I refresh my ListView?\">StackOverflow reveals</a> that there’s some controversy surrounding this issue.</p>\n\n<p>Thankfully, the accepted answer is exactly what the Android team recommends. True to StackOverflow form however, the first comment on the accepted answer with more than a handful of votes, declares that <code class=\"language-plaintext highlighter-rouge\">notifyDataSetChanged()</code> doesn’t work! <a href=\"http://stackoverflow.com/a/16708283/2306657\" title=\"StackOverflow Question: How do I refresh my ListView? Gotchas answer\">Further down</a> another user points out the gotcha’s that a lot of developers run in to; all of which, are discussed in <a href=\"http://www.youtube.com/watch?v=wDBM6wVEO70\" title=\"GoogleIO 2010 The World Of ListView\">The World of ListView from GoogleIO 2010</a> that I mentioned in the introduction to this series. If you haven’t watched it yet, I can’t recommend enough that you view it now.</p>\n\n<p>That should be the end of the story, right? Not quite. Even <a href=\"http://commonsware.com/mmurphy\" title=\"About Mark Murphy\">Mark Murphy</a>, author of <a href=\"http://commonsware.com/Android/\" title=\"The Busy Coders Guide to Android Development by Mark Murphy\">The Busy Coder’s Guide to Android Development</a> and one of the foremost Android experts recently <a href=\"http://commonsware.com/blog/2013/04/25/cwac-endlessadapter-users-upgrade-please.html\" title=\"EndlessAdapter bug fix post by Mark Murphy\">uncovered a bug in EndlessAdapter</a>; one of his open source contributions which employs <code class=\"language-plaintext highlighter-rouge\">notifyDataSetChanged()</code>.</p>\n\n<p>For us mere mortals in the Android community, the heart of this issue is almost certainly a simple misunderstanding on what <code class=\"language-plaintext highlighter-rouge\">notifyDataSetChanged()</code> and its companion <code class=\"language-plaintext highlighter-rouge\">notifyDataSetInvalidated()</code> are used for. They are used to reflect changes to (or complete invalidation of) the dataset your adapter is pulling from and should be called <em>on the UI thread immediately after making changes to your data</em>. If you’re curious about what exactly is going on behind the scenes after notifying your adapter, take a look at <a href=\"http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/AbsListView.java#5995\" title=\"AbsListView AdapterDataSetObserver implementation source\">AbsListView’s AdapterDataSetObserver</a> and its call to <a href=\"http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/AdapterView.java#AdapterView.AdapterDataSetObserver.onChanged%28%29\" title=\"AdapterView AdapterDataSetObserver implementation source\">AdapterView’s (super) implementation</a>.</p>\n\n<h2 id=\"please-recycle\">Please Recycle</h2>\n\n<p>By now I’m going to assume you’ve got warm and fuzzies about <code class=\"language-plaintext highlighter-rouge\">notifyDataSetChanged()</code> and <code class=\"language-plaintext highlighter-rouge\">notifyDataSetInvalidated()</code>. Let’s talk about what to do when you’re not making changes to your dataset, but still need to update some visual aspect of your list. You <em>could</em> scrap your whole adapter and replace it with a new one that reflects the visual changes you want, but that’s hacky and not performant. Remember that on mobile, poor performance means eating up your user’s battery even if the user doesn’t notice visual sluggishness. Fortunately, there’s a better way. You’re probably painfully aware by now that ListView and ExpandableListView use a view recycler that drastically increases performance. It achieves this by scrapping views as they fall off the visible portion of the screen and reusing only the few it needs. Those views are then returned to your adapter as the convertView parameter in <code class=\"language-plaintext highlighter-rouge\">getView(int position, View convertView, ViewGroup parent)</code>. If you’re curious about the recycler implementation, I encourage you <a href=\"http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/AbsListView.java#AbsListView.RecycleBin\" title=\"AbsListView RecycleBin source\">take a look</a> at the source. There’s even a <a href=\"http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/AbsListView.java#AbsListView.RecyclerListener\" title=\"AbsListView RecyclerListener source\">RecyclerListener</a> if you’re so inclined. This recycling strategy means we can make the visual changes we want to only the views visible on the screen and then let getView take care of making sure our recycled views look the way we want. Let’s jump in to a simple coloring example.</p>\n\n<h2 id=\"color-me-not-so-surprised\">Color Me not so Surprised</h2>\n\n<p>In the <a href=\"https://github.com/kemallette/ListExperiments\" title=\"ListView and ExpandableListView Example Project\">full example project</a> I’ve implemented some EditTexts for users to input desired text and background colors for our ListView items as well as button to apply those colors. As most of it is boiler plate, I’ll just show you the relevant bits here. ExpandableListView has some important implementation differences which make it a bit more complicated, but the strategy is the same. Feel free to skip ahead to the <a href=\"https://www.kylemallette.com/android/refreshing-lists-part2\" title=\"Jump to Refreshing ExpandableListView Example\">ExpandableListView example</a> if that’s more relevant to you.</p>\n\n<h2 id=\"listview\">ListView</h2>\n\n<h3 id=\"refreshing-visible-items\">Refreshing Visible Items</h3>\n\n<p>We’ll be using the provided <code class=\"language-plaintext highlighter-rouge\">getFirstVisiblePosition()</code>, <code class=\"language-plaintext highlighter-rouge\">getLastVisiblePosition()</code> and <code class=\"language-plaintext highlighter-rouge\">getChildAt(int position)</code> methods to grab the visible item views and make our changes. <strong>It’s important that you don’t make any structural changes to your item views.</strong> Doing so will create performance issues caused by remeasuring and conflicts with optimization assumptions ListView makes. Implement <code class=\"language-plaintext highlighter-rouge\">getItemViewType(position)</code> and <code class=\"language-plaintext highlighter-rouge\">getViewTypeCount()</code> instead for structural changes as <a href=\"http://stackoverflow.com/a/5301093/2306657\" title=\"Explanation and walk through of using different item views\">demonstrated here</a>.</p>\n\n<figure class=\"highlight\"><pre><code class=\"language-java\" data-lang=\"java\"><span class=\"c1\">// Declare the initial list item color variables</span>\n<span class=\"kd\">private</span> <span class=\"kt\">int</span> <span class=\"n\">bgColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">WHITE</span><span class=\"o\">;</span>\n<span class=\"kd\">private</span> <span class=\"kt\">int</span> <span class=\"n\">textColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">BLACK</span><span class=\"o\">;</span>\n\n\n<span class=\"cm\">/* Grabs the user color inputs and converts them proper integer color values.\n * Since we're working on ListView, two inputs are needed; text color and\n * background color.\n *\n * Definitely check out Color.parseColor(String). It's very handy!\n */</span>\n<span class=\"kd\">private</span> <span class=\"kt\">void</span> <span class=\"nf\">retrieveColors</span><span class=\"o\">()</span> <span class=\"o\">{</span>\n\n  <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mTextColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">().</span><span class=\"na\">length</span><span class=\"o\">()</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"o\">)</span>\n    <span class=\"n\">textColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">parseColor</span><span class=\"o\">(</span><span class=\"n\">mTextColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">()</span>\n                                                <span class=\"o\">.</span><span class=\"na\">toString</span><span class=\"o\">()</span>\n                                                <span class=\"o\">.</span><span class=\"na\">toLowerCase</span><span class=\"o\">());</span>\n  <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mBackgroundColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">().</span><span class=\"na\">length</span><span class=\"o\">()</span> <span class=\"o\">&gt;</span> <span class=\"mi\">0</span><span class=\"o\">)</span>\n    <span class=\"n\">bgColor</span> <span class=\"o\">=</span> <span class=\"nc\">Color</span><span class=\"o\">.</span><span class=\"na\">parseColor</span><span class=\"o\">(</span><span class=\"n\">mBackgroundColorInput</span><span class=\"o\">.</span><span class=\"na\">getText</span><span class=\"o\">()</span>\n                                                    <span class=\"o\">.</span><span class=\"na\">toString</span><span class=\"o\">()</span>\n                                                    <span class=\"o\">.</span><span class=\"na\">toLowerCase</span><span class=\"o\">());</span>\n<span class=\"o\">}</span>\n\n<span class=\"cm\">/* Applies the user supplied color values to the visible list items. This\n * does not touch the recycled off screen views.\n */</span>\n<span class=\"kd\">private</span> <span class=\"kt\">void</span> <span class=\"nf\">applyColors</span><span class=\"o\">()</span> <span class=\"o\">{</span>\n\n  <span class=\"nc\">View</span> <span class=\"n\">listItem</span><span class=\"o\">;</span>\n  <span class=\"nc\">Holder</span> <span class=\"n\">mHolder</span><span class=\"o\">;</span>\n\n  <span class=\"n\">retrieveColors</span><span class=\"o\">();</span> <span class=\"c1\">//First we collect our user input and</span>\n                    <span class=\"c1\">//convert it to valid integer color values</span>\n\n  <span class=\"c1\">// These are both implemented in AdapterView which means</span>\n  <span class=\"c1\">// they're flat list positions</span>\n  <span class=\"kt\">int</span> <span class=\"n\">firstVis</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getFirstVisiblePosition</span><span class=\"o\">();</span>\n  <span class=\"kt\">int</span> <span class=\"n\">lastVis</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getLastVisiblePosition</span><span class=\"o\">();</span>\n\n  <span class=\"cm\">/* This is the \"conversion\" from flat list positions to ViewGroup child positions */</span>\n  <span class=\"kt\">int</span> <span class=\"n\">count</span> <span class=\"o\">=</span> <span class=\"n\">lastVis</span> <span class=\"o\">-</span> <span class=\"n\">firstVis</span><span class=\"o\">;</span>\n\n  <span class=\"k\">while</span> <span class=\"o\">(</span><span class=\"n\">count</span> <span class=\"o\">&gt;=</span> <span class=\"mi\">0</span><span class=\"o\">)</span> <span class=\"o\">{</span>  <span class=\"c1\">// looping through visible list items</span>\n\n    <span class=\"cm\">/*  getChildAt(pos) is implemented in ViewGroup and has a different meaning for\n     *  its position values. ViewGroup tracks visible items as children and is 0 indexed.\n     *  This means you'll have 0 - X positions where X is however many items it takes\n     *  to fill the visible area of your screen; usually less than 10. */</span>\n    <span class=\"n\">listItem</span> <span class=\"o\">=</span> <span class=\"n\">mList</span><span class=\"o\">.</span><span class=\"na\">getChildAt</span><span class=\"o\">(</span><span class=\"n\">count</span><span class=\"o\">);</span>\n\n    <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">listItem</span> <span class=\"o\">!=</span> <span class=\"kc\">null</span><span class=\"o\">)</span> <span class=\"o\">{</span>\n\n      <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">Holder</span><span class=\"o\">)</span> <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">getTag</span><span class=\"o\">();</span>\n      <span class=\"k\">if</span> <span class=\"o\">(</span><span class=\"n\">mHolder</span> <span class=\"o\">==</span> <span class=\"kc\">null</span><span class=\"o\">)</span> <span class=\"o\">{</span>  <span class=\"c1\">// This shouldn't happen, but we'll make</span>\n                              <span class=\"c1\">// sure in case some strange concurrency</span>\n                              <span class=\"c1\">// bugs appear</span>\n        <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"k\">new</span> <span class=\"nc\">Holder</span><span class=\"o\">();</span>\n        <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">TextView</span><span class=\"o\">)</span> <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">findViewById</span><span class=\"o\">(</span><span class=\"n\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">id</span><span class=\"o\">.</span><span class=\"na\">text1</span><span class=\"o\">);</span>\n        <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">setTag</span><span class=\"o\">(</span><span class=\"n\">mHolder</span><span class=\"o\">);</span>\n      <span class=\"o\">}</span>\n\n      <span class=\"n\">listItem</span><span class=\"o\">.</span><span class=\"na\">setBackgroundColor</span><span class=\"o\">(</span><span class=\"n\">bgColor</span><span class=\"o\">);</span> <span class=\"c1\">// Setting our user input</span>\n                                            <span class=\"c1\">// background color</span>\n      <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setTextColor</span><span class=\"o\">(</span><span class=\"n\">textColor</span><span class=\"o\">);</span><span class=\"c1\">// Setting our user input</span>\n                                            <span class=\"c1\">// text color</span>\n    <span class=\"o\">}</span> <span class=\"k\">else</span>\n      <span class=\"nc\">Log</span><span class=\"o\">.</span><span class=\"na\">d</span><span class=\"o\">(</span><span class=\"no\">TAG</span><span class=\"o\">,</span> <span class=\"s\">\"getChildAt retrieved a null view :( \"</span><span class=\"o\">);</span>\n\n    <span class=\"n\">count</span><span class=\"o\">--;</span>\n  <span class=\"o\">}</span>\n<span class=\"o\">}</span></code></pre></figure>\n\n<h3 id=\"applying-changes-to-all-items\">Applying Changes to All Items</h3>\n<p>Now that we’ve got our visible item updates working, we need to make sure all of our items reflect our color changes. For this, we just need to override our adapter’s <code class=\"language-plaintext highlighter-rouge\">getView(int position, View convertView, ViewGroup parent)</code> method and ensure that each convertView we get shows the correct colors.</p>\n\n<figure class=\"highlight\"><pre><code class=\"language-java\" data-lang=\"java\"><span class=\"nd\">@Override</span>\n<span class=\"kd\">public</span> <span class=\"nc\">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=\"nc\">View</span> <span class=\"n\">convertView</span><span class=\"o\">,</span> <span class=\"nc\">ViewGroup</span> <span class=\"n\">parent</span><span class=\"o\">){</span>\n\n  <span class=\"nc\">Holder</span> <span class=\"n\">mHolder</span><span class=\"o\">;</span>\n\n  <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=\"c1\">// ViewHolder pattern implementation</span>\n    <span class=\"n\">convertView</span> <span class=\"o\">=</span> <span class=\"n\">getLayoutInflater</span><span class=\"o\">().</span><span class=\"na\">inflate</span><span class=\"o\">(</span><span class=\"n\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">layout</span><span class=\"o\">.</span><span class=\"na\">simple_list_item_1</span><span class=\"o\">,</span>\n                                              <span class=\"n\">parent</span><span class=\"o\">,</span>\n                                              <span class=\"kc\">false</span><span class=\"o\">);</span>\n    <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"k\">new</span> <span class=\"nc\">Holder</span><span class=\"o\">();</span>\n    <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">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\">android</span><span class=\"o\">.</span><span class=\"na\">R</span><span class=\"o\">.</span><span class=\"na\">id</span><span class=\"o\">.</span><span class=\"na\">text1</span><span class=\"o\">);</span>\n    <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">setTag</span><span class=\"o\">(</span><span class=\"n\">mHolder</span><span class=\"o\">);</span>\n  <span class=\"o\">}</span><span class=\"k\">else</span>\n    <span class=\"n\">mHolder</span> <span class=\"o\">=</span> <span class=\"o\">(</span><span class=\"nc\">Holder</span><span class=\"o\">)</span> <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">getTag</span><span class=\"o\">();</span>\n\n<span class=\"cm\">/* Since all visible items have had their appropriate user selected\n * colors applied, we need to make sure any of the recycler's\n * scrapped views (which wouldn't be touched by our visible item\n * changes) also reflect our changes. */</span>\n  <span class=\"n\">convertView</span><span class=\"o\">.</span><span class=\"na\">setBackgroundColor</span><span class=\"o\">(</span><span class=\"n\">bgColor</span><span class=\"o\">);</span>\n  <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setTextColor</span><span class=\"o\">(</span><span class=\"n\">textColor</span><span class=\"o\">);</span>\n\n  <span class=\"n\">mHolder</span><span class=\"o\">.</span><span class=\"na\">mText</span><span class=\"o\">.</span><span class=\"na\">setText</span><span class=\"o\">(</span><span class=\"n\">getItem</span><span class=\"o\">(</span><span class=\"n\">position</span><span class=\"o\">).</span><span class=\"na\">toString</span><span class=\"o\">());</span>\n\n  <span class=\"k\">return</span> <span class=\"n\">convertView</span><span class=\"o\">;</span>\n<span class=\"o\">}</span></code></pre></figure>\n\n",
      "date_published": "2013-09-15T00:00:00+00:00",
      "tags": ["Exploring Lists Series","ListView","ExpandableListView"],
      "image": "https://www.kylemallette.com/images/art/photography/st-johns-piano.jpg",
      "_markdown": { "about": "https://llmstxt.org", "url": "https://www.kylemallette.com/android/2013/09/15/refreshing-lists-part1.html.md" }
    },
    {
      "id": "https://www.kylemallette.com/android/2013/09/09/exploring-list-expandablelist-adapters.html",
      "url": "https://www.kylemallette.com/android/2013/09/09/exploring-list-expandablelist-adapters.html",
      "title": "Exploring Lists and Adapters",
      "summary": "An introduction to Android's ListView, ExpandableListView, and AbsListView, the adapters behind them, and why they trip up so many developers.",
      "content_html": "<p><img src=\"https://www.kylemallette.com/images/android_facepalm.png\" alt=\"Android ListView Facepalm Clipart\" class=\"float-left\" />\nIf you’re working with Android, chances are you’ve run in to issues with <a href=\"http://developer.android.com/reference/android/widget/ListView.html\">ListView</a>, <a href=\"http://developer.android.com/reference/android/widget/ExpandableListView.html\">ExpandableListView</a> or their parent, <a href=\"http://developer.android.com/reference/android/widget/AbsListView.html\">AbsListView</a>. I’m not ashamed to admit spending more than a couple evenings staring angrily at misbehaving lists and adapters. It’s almost a right of passage for new Android devs.</p>\n\n<p>The most frequently referenced question out of all Android tagged questions on StackOverflow is <a href=\"http://stackoverflow.com/questions/541966/how-do-i-do-a-lazy-load-of-images-in-listview\">“How do I do a lazy load of images in ListView?”</a>. Answering requires a non-trivial understanding of how these components and their adapters work along with a healthy dose of Android concurrency patterns. Poking around Stack Overflow, I found that of 380,906 Android tagged questions at the time of this posting, roughly 25,000 sport tags closely related to ListView, ExpandableListView or their Adapter partners roughly representing <strong>5%</strong> of all Android tagged questions. In response, I’m kicking off a series of posts centered on ListView, ExpandableListView and their related Adapter partners. The basics and some much needed best practices are <a href=\"http://www.youtube.com/watch?v=wDBM6wVEO70\">covered well</a><sup><a href=\"#GoogleIO2010WorldOfListView\" id=\"ref2\">2</a></sup> and distributed broadly. Instead, I’m going to provide some working examples to reveal a few unexplored gotcha’s in ListView and the oft ignored ExpandableListView. Along the way, I’m going to slice open the source code reveal some of the least exposed innards of these components. There’s no better way to truly understand a framework than to dive in to the source. Enjoy!</p>\n\n<p><sup id=\"GoogleIO2010WorldOfListView\">\n    [2] If you haven’t seen The World Of ListView video from GoogleIO 2010, watch it before you write another piece of code relating to a ListView or Adapter! I can’t recommend it enough.\n    <a href=\"#ref2\" title=\"Jump back to footnote 2\"><big>↩</big></a>\n</sup></p>\n\n",
      "date_published": "2013-09-09T00:00:00+00:00",
      "tags": ["Exploring Lists Series","ListView","ExpandableListView"],
      "image": "https://www.kylemallette.com/images/art/photography/st-johns-piano.jpg",
      "_markdown": { "about": "https://llmstxt.org", "url": "https://www.kylemallette.com/android/2013/09/09/exploring-list-expandablelist-adapters.html.md" }
    }
  ]
}
