<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Sangsoo Nam | Unlimited Power</title>
    <description>I’m a tech leader passionate about finding ways to improve collaboration across teams and make technical work more productive
</description>
    <link>http://sangsoonam.github.io/</link>
    <atom:link href="http://sangsoonam.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 18 Aug 2025 04:26:54 +0000</pubDate>
    <lastBuildDate>Mon, 18 Aug 2025 04:26:54 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Git: Restore a Commit with Reflog</title>
        <description>&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt; is generally used to cancel a commit. It happens mainly for two reasons. One is just to cancel it. The other is to modify changes. After changes, a new commit can be created. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt; is an alternative way to modify it. Both ways can make the same result.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
a91929a &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add skeleton files
6e9be90 Add .gitignore
be44318 Init

▶ git reset HEAD^

▶ git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
6e9be90 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add .gitignore
be44318 Init

▶ git st
On branch master
Untracked files:
  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;s2&quot;&gt;&quot;git add &amp;lt;file&amp;gt;...&quot;&lt;/span&gt; to include &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;what will be committed&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  package.json
  yarn.lock
  app.tsx
  index.html

nothing added to commit but untracked files present &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use &lt;span class=&quot;s2&quot;&gt;&quot;git add&quot;&lt;/span&gt; to track&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These commands are quite useful and powerful. The thing is that I sometimes want to cancel those and restore the previous commit.  After &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt;, it is gone. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git log&lt;/code&gt; doesn’t show it anymore.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
6e9be90 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add .gitignore
be44318 Init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Then, what would be the way to restore it? Maybe you pushed a branch or a commit to a remote repository before. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt; happens only in a local machine, it’s possible to get or restore it from the remote repository. If not, it can be tricky.. Luckily, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; has reference logs. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; document describes&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Reference logs, or “reflogs”, record when the tips of branches and other references were updated in the local repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; doesn’t remove commits right away when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt; happen. It changes references first. In this example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; is now changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6e9be90&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; shows those reference change logs. These logs are stored only locally and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; will prune reference logs older than 90 days by default. The below command shows the commit id, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a91929a&lt;/code&gt;, before running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset HEAD^&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git reflog
6e9be90 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: reset: moving to HEAD^
a91929a HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit: Add skeleton files
6e9be90 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit: Add .gitignore
be44318 HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;initial&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: Init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset --hard &amp;lt;COMMIT_ID&amp;gt;&lt;/code&gt; would restore that commit and references.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; a91929a
HEAD is now at a91929a Add skeleton files

▶ git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
a91929a &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add skeleton files
6e9be90 Add .gitignore
be44318 Init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The same way is applicable to restore after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt;. This command is used to apply more changes to the existing commit. Technically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt; does’t modify an existing commit. It will create a new commit using the changes of the most recent existing commit. Then, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; adjust references to show only the new commit. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git log&lt;/code&gt; doesn’t show that previously existing commit.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git commit &lt;span class=&quot;nt&quot;&gt;--amend&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;master 447608a] Add skeleton files
 ...

▶ git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
447608a &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add skeleton files
6e9be90 Add .gitignore
be44318 Init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It means that it would be easy to restore by knowing that previously existing commit id. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; shows those records. The commit id before amending is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a91929a&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git reflog
447608a &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;amend&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: Add skeleton files
a91929a HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: reset: moving to a91929a
6e9be90 HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: reset: moving to HEAD^
a91929a HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit: Add skeleton files
6e9be90 HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;4&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit: Add .gitignore
be44318 HEAD@&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;: commit &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;initial&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: Init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset --hard&lt;/code&gt; command will restore that commit and references.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;▶ git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; a91929a
HEAD is now at a91929a Add skeleton files

▶ git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
a91929a &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Add skeleton files
6e9be90 Add .gitignore
be44318 Init&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;One more thing. If you want to learn more on references, try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git cat-file -p &amp;lt;COMMIT_ID|BRANCH&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;# After `git reset --hard a91929a`, the references are the same as `a91929a`&lt;/span&gt;
▶ git cat-file &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; master
tree 3f5d073729ffc62a7a1f9e307ba510a3f4762ea9
parent 6e9be90d94f41e176f1a5a9a706e14fdb10f1586

&lt;span class=&quot;c&quot;&gt;# `a91929a` have a parent, `6e9be90`&lt;/span&gt;
▶ git cat-file &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; a91929a
tree 3f5d073729ffc62a7a1f9e307ba510a3f4762ea9
parent 6e9be90d94f41e176f1a5a9a706e14fdb10f1586

&lt;span class=&quot;c&quot;&gt;# Previously amend commit has the same parent, `6e89e90`&lt;/span&gt;
▶ git cat-file &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 447608a
tree 3f5d073729ffc62a7a1f9e307ba510a3f4762ea9
parent 6e9be90d94f41e176f1a5a9a706e14fdb10f1586&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</description>
        <pubDate>Mon, 25 Jul 2022 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2022/07/25/git-restore-a-commit-with-reflog.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2022/07/25/git-restore-a-commit-with-reflog.html</guid>
        
        
      </item>
    
      <item>
        <title>Bash: Highlight Matched Texts With Colors</title>
        <description>&lt;p&gt;Logs are valuable sources to identify issues. It would be continuously generated (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb logcat&lt;/code&gt;) or stored as a file. Mostly, I use the terminal to check those. When I check that, it is often not easy to see since every text has the same color. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; could help to filter out. With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--color=auto&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--color=always&lt;/code&gt; option, it supports highlighting texts as well. However, there are cases I don’t want to filter out but want to highlight certain texts or words to check easily. This happens more frequently when I check continuous logs.&lt;/p&gt;

&lt;p&gt;After some investigation, I’ve figured out how to do it in bash. By adding the below function, you can highlight a matched text with a specified color.&lt;/p&gt;

&lt;p class=&quot;code-label&quot;&gt;.bash_profile&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;highlight&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Usage: highlight &amp;lt;color&amp;gt; &amp;lt;text&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Foreground colors&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 30:black, 31:red, 32:green, 33:yellow, 34:blue, 35:magenta, 36:cyan&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;# Background colors&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# ---&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 40:black, 41:red, 42:green, 43:yellow, 44:blue, 45:magenta, 46:cyan&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;escape&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\033&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;s,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;escape&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1m&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;escape&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[0m,g&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The actual showing color is determined by terminal settings. For example, &lt;em&gt;iTerm&lt;/em&gt; defines colors in &lt;em&gt;Profiles &amp;gt; Colors&lt;/em&gt;.
&lt;img src=&quot;/images/2020/12-24/iterms-colors.png&quot; alt=&quot;iTerm Colors&quot; /&gt;&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Here is an example on how to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;highlight&lt;/code&gt; and how the result looks.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;Hello | highlight 31 H | highlight 32 e | highlight 33 l | highlight 34 o&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020/12-24/highlight-hello.png&quot; alt=&quot;Highlight Hello&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Though this function works well, it requires quite a long command if I want to highlight multiple texts, as you can see above. Specifying a color is great, but it becomes somewhat cumbersome if it is needed every time. All I need is just to highlight texts with different colors. Based on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;highlight&lt;/code&gt; function, the below helper function simplifies it.&lt;/p&gt;
&lt;p class=&quot;code-label&quot;&gt;.bash_profile&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;ht&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 1 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;highlight 31 &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi
  if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 2 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;highlight 31 &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | highlight 32 &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi
  if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 3 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;highlight 31 &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | highlight 32 &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; | highlight 33 &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi
  if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$# &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 4 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;highlight 31 &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | highlight 32 &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; | highlight 33 &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; | highlight 34 &lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020/12-24/ht-hello.png&quot; alt=&quot;ht Logcat&quot; /&gt;
&lt;img src=&quot;/images/2020/12-24/ht-logcat.png&quot; alt=&quot;ht Logcat&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Thu, 24 Dec 2020 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2020/12/24/bash-highlight-matched-texts-with-colors.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2020/12/24/bash-highlight-matched-texts-with-colors.html</guid>
        
        
      </item>
    
      <item>
        <title>Failing Unit Test by GeneratedSerializationConstructorAccessor1</title>
        <description>&lt;p&gt;For running Gradle tasks, I prefer using a command-line interface. Recently, I made a code change and added new unit tests. To verify the behavior, I ran a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; task. Soon after, it showed a quite weird error message, which was about &lt;em&gt;GeneratedSerializationConstructorAccessor1&lt;/em&gt;. As you can see below, the error message didn’t point out any line from my code. Everything was related to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt;. When I made a pull request, TeamCity ran the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; task without any issue. It made me curious and I wanted to solve this issue.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./gradlew &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; Task :app:testDebugUnitTest
...
java.lang.NoClassDefFoundError: jdk/internal/reflect/GeneratedSerializationConstructorAccessor1
        at jdk.internal.reflect.GeneratedSerializationConstructorAccessor1.newInstance&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Unknown Source&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Constructor.java:500&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.lang.reflect.Constructor.newInstance&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Constructor.java:481&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.io.ObjectStreamClass.newInstance&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ObjectStreamClass.java:1081&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.io.ObjectInputStream.readOrdinaryObject&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ObjectInputStream.java:2071&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.io.ObjectInputStream.readObject0&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ObjectInputStream.java:1594&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.io.ObjectInputStream.readObject&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ObjectInputStream.java:430&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SystemApplicationClassLoaderWorker.java:107&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SystemApplicationClassLoaderWorker.java:64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.run&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GradleWorkerMain.java:62&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.main&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GradleWorkerMain.java:67&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Caused by: java.lang.ClassNotFoundException: jdk.internal.reflect.GeneratedSerializationConstructorAccessor1
        at java.base/java.net.URLClassLoader.findClass&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;URLClassLoader.java:436&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.lang.ClassLoader.loadClass&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ClassLoader.java:588&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        at java.base/java.lang.ClassLoader.loadClass&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ClassLoader.java:521&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        ... 11 more
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;The error message could vary slightly depending on your &lt;em&gt;Jacoco&lt;/em&gt; tool version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This error message showed some lines in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt;. Since there was no issue in TeamCity, it might be a bug in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt; and possibly I used a different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt; version from what TeamCity used.&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;java &lt;span class=&quot;nt&quot;&gt;-version&lt;/span&gt;
java version &lt;span class=&quot;s2&quot;&gt;&quot;12.0.2&quot;&lt;/span&gt; 2019-07-16
Java&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;TM&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; SE Runtime Environment &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;build 12.0.2+10&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Java HotSpot&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;TM&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 64-Bit Server VM &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;build 12.0.2+10, mixed mode, sharing&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;TeamCity used Java 8 and my machine used Java 12. I updated my Java version to work on backend services, which now requires higher that Java 11. After updating, Gradle seemed work well. I could run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assemble&lt;/code&gt; task. The problem only happened for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; task strangely.&lt;/p&gt;

&lt;p&gt;After researching deeply, this turned out a quite complex problem. In short, Java 8 and higher versions (e.g. Java 9, Java 10, …) are different. Plugins or libraries should support higher versions to work properly. For me, they are &lt;em&gt;Jacoco&lt;/em&gt;, &lt;em&gt;Mockito&lt;/em&gt;, and &lt;em&gt;PowerMock&lt;/em&gt;. There are quite typical plugins/libraries for Android testing.&lt;/p&gt;

&lt;p&gt;For &lt;em&gt;Jacoco&lt;/em&gt;, you can fix this issue by updating the plugin version and adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jacoco.excludes&lt;/code&gt;.(&lt;a href=&quot;https://github.com/gradle/gradle/issues/5184&quot;&gt;Gradle issue #5184&lt;/a&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;jacoco&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;toolVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;0.8.4&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;jacoco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;includeNoLocationClasses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;jacoco&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;excludes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jdk.internal.*&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Mockito&lt;/em&gt; [had an update (&lt;a href=&quot;https://github.com/mockito/mockito/pull/1250&quot;&gt;Mockito PR #1250&lt;/a&gt;) to support this. If you see below error, you need to update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mockito-core&lt;/code&gt; to use the latest version. The current project used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.8.9&lt;/code&gt; version which is quite old and didn’t have that update. The latest &lt;em&gt;Mockito&lt;/em&gt; version at this point is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.28.2&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gradlew&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;app:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;testDebugUnitTest&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ExampleTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;basicFunctionality&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FAILED&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mockito&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;exceptions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;MockitoException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExampleTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Caused&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;by:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;UnsupportedOperationException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExampleTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Caused&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;by:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;IllegalArgumentException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExampleTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For me, there was another hurdle. It still didn’t work and it was due to &lt;em&gt;PowerMock&lt;/em&gt;. Unfortunately, it seemed not fixed yet (&lt;a href=&quot;https://github.com/powermock/powermock/issues/901&quot;&gt;Powermock issue #901&lt;/a&gt;).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;n&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gradlew&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Task&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;app:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;testDebugUnitTest&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ExampleText&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initializationError&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FAILED&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;objenesis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ObjenesisException&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Caused&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;by:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;reflect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;InvocationTargetException&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Caused&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;by:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;IllegalAccessError&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you don’t use &lt;em&gt;PowerMock&lt;/em&gt; library, updating libraries and setting excludes of &lt;em&gt;Jacoco&lt;/em&gt; would fix your issue. In my case, however, it was tricky because of &lt;em&gt;PowerMock&lt;/em&gt;. There might be some way to work around but it seemed not worth spending more time. As you know, the issue was caused by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt;. It means that this could be easily solved by using Java 8 instead of Java 12. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jenv&lt;/code&gt;(https://www.jenv.be) helps to manage/switch multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt;s in the same machine. Using that, I was able to fix all my issue and to switch Java 12 when I need to work on the backend code.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;jenv versions
  oracle64-1.8.0.221
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; oracle64-12.0.2 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;by /Users/sangsoo/.jenv/version&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;jenv global oracle64-1.8.0.221&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you use Android Studio to run gradle tasks including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt;, you might not see this issue. Android Studio allows you to set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk&lt;/code&gt;. It could be different from your command line environment. By default, Android Studio uses an embedded JDK, which is Java 8.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/08-15/android-studio-embedded-jdk.png&quot; alt=&quot;Android Studio Embedded JDK&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 15 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/08/15/failing-unit-test-by-generatedserializationconstructoraccessor1.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/08/15/failing-unit-test-by-generatedserializationconstructoraccessor1.html</guid>
        
        
      </item>
    
      <item>
        <title>Why ZSH is Slow for Git Repos</title>
        <description>&lt;p&gt;In these days, I’m using ZSH(&lt;a href=&quot;https://ohmyz.sh/&quot;&gt;https://ohmyz.sh/&lt;/a&gt;). It has many handy features and supports useful plugins. One day, I’ve noticed a slowness issue. Basically, the prompt was not shown right after running a command. It was interesting because it only happened in the git repositories. To fix this issue, I needed to understand what’s happening first.&lt;/p&gt;

&lt;p&gt;When you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt; with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt; parameter, you can see many options. Among them, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-x&lt;/code&gt; are useful ones to dig into the problem.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zsh &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
...
&lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;    equivalent to &lt;span class=&quot;nt&quot;&gt;--verbose&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt;    equivalent to &lt;span class=&quot;nt&quot;&gt;--xtrace&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh -xv&lt;/code&gt;, every command that ZSH runs will be shown. In the git repo, I pressed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enter&lt;/code&gt; multiple times and checked logs to figure out which command is slow. There might be some better ways but I just looked at the terminal. I saw that there was a bit freeze when the below line was shown.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zsh &lt;span class=&quot;nt&quot;&gt;-vx&lt;/span&gt;
...
+git_prompt_status:1&amp;gt; &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;INDEX STATUS
+git_prompt_status:2&amp;gt; &lt;span class=&quot;nv&quot;&gt;INDEX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;+git_prompt_status:2&amp;gt; git status &lt;span class=&quot;nt&quot;&gt;--porcelain&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;To show helpful information on the prompt, ZSH has many defined functions. Git related functions are defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git.zsh&lt;/code&gt;. As you can see, that command is from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_prompt_status()&lt;/code&gt;.&lt;/p&gt;

&lt;p class=&quot;code-label&quot;&gt;.oh-my-zsh/lib/git.zsh&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;...
&lt;span class=&quot;c&quot;&gt;# Get the status of the working tree&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;git_prompt_status&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;INDEX STATUS
  &lt;span class=&quot;nv&quot;&gt;INDEX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;git status &lt;span class=&quot;nt&quot;&gt;--porcelain&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 2&amp;gt; /dev/null&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;STATUS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Those functions are generally called by ZSH themes and plugins. In my case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;avit&lt;/code&gt; theme, I’m currently using, uses it to set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RPROMPT&lt;/code&gt;.&lt;/p&gt;

&lt;p class=&quot;code-label&quot;&gt;.oh-my-zsh/themes/avit.zsh-theme&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;...
&lt;span class=&quot;nv&quot;&gt;RPROMPT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;$(_vi_status){$(echotc UP 1)%}$(_git_time_since_commit) $(git_prompt_status) ${_return_status}%{$(echotc DO 1)%}&apos;&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It is possible to fix or optimize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_prompt_status()&lt;/code&gt; function in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git.zsh&lt;/code&gt;. However, I realized that it was the information that I didn’t need actually. So, I decided to remove that. One way is to remove that line in the theme directory. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.oh_my_zsh&lt;/code&gt; is a git repo. So, modifying the code in there could make an issue to update ZSH. Instead of that, I simply override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RPROMPT&lt;/code&gt; value in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;. This is a safer approach.&lt;/p&gt;

&lt;p class=&quot;code-label&quot;&gt;.zshrc&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;...
&lt;span class=&quot;nv&quot;&gt;RPROMPT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt;
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that a problem line could vary depending on your theme and plugins. When you have some issues, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh -vx&lt;/code&gt; will help you to point a problem command.&lt;/p&gt;
</description>
        <pubDate>Mon, 05 Aug 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/08/05/why-zsh-is-slow-for-git-repos.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/08/05/why-zsh-is-slow-for-git-repos.html</guid>
        
        
      </item>
    
      <item>
        <title>How to Embed a Google Drive Video on a Website</title>
        <description>&lt;p&gt;There are lots of video sites you can upload your videos. After uploading, you can easily embed that video on your post or on a website. For example, YouTube supports &lt;em&gt;“Copy embed code”&lt;/em&gt; option when you do the right-click.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/07-27/youtube-embed-code.png&quot; alt=&quot;YouTube embed code&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The copied code is like below. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt; tag is used to embed a video, and there are other parameters such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowfullscreen&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;766&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;431&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.youtube.com/embed/hVGVcmW0crs&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;frameborder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;allow=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;accelerometer; autoplay; encrypted-media; gyroscope;
picture-in-picture&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;allowfullscreen&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it is easy to embed videos on your site. Although there are well-known services, you might consider embedding a Google drive video rather than using them. There are several benefits. When you upload your video, most sites consider that as public. It means that you might not be able to specify who you want to show. When you share something from Google drive, you can easily set who can see. It also has a handy permission scope, an organization.&lt;/p&gt;

&lt;p&gt;That being said, embedding a Google drive video supports a better permission scope and security. If you consider it, here are the steps. After uploading your video, you first need to share it. You can set specific users or an organization.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/07-27/gdrive-share.png&quot; alt=&quot;Google drive share&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unlike YouTube, finding &lt;em&gt;“Embed code”&lt;/em&gt; in Google drive is not straightforward. First of all, you need to click &lt;em&gt;“Preview”&lt;/em&gt;.
&lt;img src=&quot;/images/2019/07-27/gdrive-preview.png&quot; alt=&quot;Google drive preview&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then, open the menu by pressing the top-right icon, and click &lt;em&gt;“Open in new window”&lt;/em&gt;. That will open a new tab.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/07-27/gdrive-open-in-new-window.png&quot; alt=&quot;Google drive preview&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When you open the menu again in that tab, you will see the option, &lt;em&gt;“Embed item…“&lt;/em&gt;.
&lt;img src=&quot;/images/2019/07-27/gdrive-embed-item.png&quot; alt=&quot;Google drive embed item&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Finally, you can copy the embed code and paste it on your site.
&lt;img src=&quot;/images/2019/07-27/gdrive-embed-item-code.png&quot; alt=&quot;Google drive embed item code&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that full screen mode is not allowed if you just copy and paste that code. You can allow it by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowfullscreen&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/07-27/gdrive-full-screen.png&quot; alt=&quot;Google drive full screen&quot; /&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://drive.google.com/file/d/1rLT6EI-example/preview&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;640&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;480&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;allowfullscreen&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/07/27/how-to-embed-a-google-drive-video.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/07/27/how-to-embed-a-google-drive-video.html</guid>
        
        
      </item>
    
      <item>
        <title>Adb: Take a Screenshot with a Laptop</title>
        <description>&lt;p&gt;When you use an Android emulator, taking a screenshot is quite easy. Just press the ‘Take screenshot’ on the sidebar or press the shortcut (For Mac, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⌘&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;). However, it is slightly cumbersome if you want to take a screenshot from your device and store that in your laptop. The reason is that you need to pull a screenshot file after taking a screenshot in the device.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/07-19/emulator-take-screenshot.png&quot; alt=&quot;Emulator Take Screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When the device is connected to your laptop, you can do it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adb&lt;/code&gt; commands: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pull&lt;/code&gt;. The first command takes a screenshot and store into your device. The second command pulls it to your laptop from the Android device. Although it works, it makes a bit unnecessary intermediate file in your device, which is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screenshot.png&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb shell screencap &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /sdcard/screenshot.png
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb pull /sdcard/screenshot.png&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In addition to an intermediate file, this requires two commands. This is not a big deal but you may want to find a simpler way. If you are looking for it, below command is it. This command takes a screenshot from the connected device and stores it on your laptop.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb exec-out screencap &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; screenshot.png&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;This command saves a screenshot to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screenshot.png&lt;/code&gt;. As you notice, this will overwrite an existing file when you run multiple times. You probably don’t want to do. When you click ‘Take screenshot’ on Android emulator, it uses a naming convention, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Screenshot_{unix_timestamp}.png&lt;/code&gt;. To do the same behavior, you can utilize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date&lt;/code&gt; command.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb exec-out screencap &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; +Screenshot_%s.png&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you run this frequently, you can set an alias for that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p class=&quot;code-label&quot;&gt;.zshrc&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;asc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;adb exec-out screencap -p &amp;gt; `date +Screenshot_%s.png`&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This command is enough for most cases. However, there is still some chance to overwrite because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unix_timestamp&lt;/code&gt; uses seconds. If you concern that, you can add a millisecond additionally. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%N&lt;/code&gt; returns nanoseconds and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%3N&lt;/code&gt; returns milliseconds by cutting the first 3 digits.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb exec-out screencap &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; +Screenshot_%s.%3N.png&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Unfortunately, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date&lt;/code&gt; command in the mac doesn’t support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%N&lt;/code&gt;. So, you can’t get milliseconds. If you have this issue, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdate&lt;/code&gt;(GNU date) command.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;coreutils
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb exec-out screencap &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gdate +Screenshot_%s.%3N.png&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew install coreutils&lt;/code&gt; installs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdate&lt;/code&gt; on Mac.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 19 Jul 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/07/19/take-a-screenshot-with-a-laptop.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/07/19/take-a-screenshot-with-a-laptop.html</guid>
        
        
      </item>
    
      <item>
        <title>RxJava: Fail Early and Track Errors</title>
        <description>&lt;p&gt;In RxJava, &lt;em&gt;Publisher&lt;/em&gt; emits events and you can subscribe to those events with &lt;em&gt;Consumer&lt;/em&gt;. While subscribing, emitted events can be used to update the view or to do something else. Below example shows a simple example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Publisher. Events could be from the network or database.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;subscribeOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Schedulers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;observeOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AndroidSchedulers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mainThread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Consumer&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;userTextView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code work well while &lt;em&gt;Publisher&lt;/em&gt; emits events without any error. However, there could be several issues to emit events. Those vary depending on where events are generated. For example, if &lt;em&gt;Publisher&lt;/em&gt; is related to the network, it could have a bad connection or no response from a backend service. In that situation, an error will be thrown. The current code doesn’t have any logic to consume that error, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnErrorMissingConsumer&lt;/code&gt; exception happens. That exception makes an app crash.&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;The crash will tell you what went wrong. Although it is useful, you don’t want to make a crash in some cases. Some logic doesn’t affect the main experience, or a user can trigger to subscribe again easily. So, you can set an error consumer to handle those errors and avoid a crash. One way is just to print an error log.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Publisher. Events could be from the network or database.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;subscribeOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Schedulers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;observeOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AndroidSchedulers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mainThread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Event Consumer&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;userTextView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setText&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Error Consumer&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;TAG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Failed to get the user name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It looks good, but it has some potential issues.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;This doesn’t make a crash, so it is easy to miss. Error logs are often not enough to grab attention.&lt;/li&gt;
  &lt;li&gt;There is no way to know how many people have errors. If your backend service is down, all users will have a network error. By tracking errors, you can keep giving a better experience continuously.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thus, what we want to achieve is to track errors in the release and to make a crash while developing, which helps early detection. &lt;em&gt;Crashlytics&lt;/em&gt; is one of the useful tools for tracking errors. You can track errors by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Crashlytics.logException&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nc&quot;&gt;Crashlytics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;logException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BuildConfig.DEBUG&lt;/code&gt; tells whether the build is a release or a debug. TO sum up, you can resolve those issues like below.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Error Consumer&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;RxJavaErrorHandler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RxJavaErrorHandler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Throwable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BuildConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentThread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getUncaughtExceptionHandler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;uncaughtException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentThread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;

            &lt;span class=&quot;nc&quot;&gt;Crashlytics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;logException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;throwable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;blockquote&gt;
  &lt;p&gt;Some exceptions/throwables could be not needed to make a crash in your application. You can check with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instanceof&lt;/code&gt; and ignore them.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sun, 14 Jul 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/07/14/rxjava-fail-early-and-track-errors.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/07/14/rxjava-fail-early-and-track-errors.html</guid>
        
        
      </item>
    
      <item>
        <title>Use the &amp;lt;merge&amp;gt; Tag for Optimizing View Tree</title>
        <description>&lt;p&gt;In Android, a view is one of the basic blocks for user interface components. It is a tree structure and you can nest views to display what you want to show. If the tree height gets longer, it can lead to some performance issue. The reason is that the Android framework does a top-down traversal of the view tree two times: a measure pass and a layout pass. Thus, it is important to keep in mind to make the view tree height short as much as possible.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FrameLayout&lt;/code&gt; is one of the views, and it allows placements of views along the z-axis. So, you can stack view elements. In addition that, you can align views with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout_gravity&lt;/code&gt; attribute. Here is an example.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;FrameLayout&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:android=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.android.com/apk/res/android&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;android:layout_width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;match_parent&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;android:layout_height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;match_parent&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_gravity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;center&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:textSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;20sp&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_gravity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bottom|center&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Button&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/FrameLayout&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;While running the application, you can capture the view tree. Click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tools &amp;gt; Layout Inspector&lt;/code&gt;. Then, you can see the below screen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/03-20/layout-inspect-frame-layout.png&quot; alt=&quot;layout-inspect-frame-layout&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the layout file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FrameLayout&lt;/code&gt; is the root view. That is true if you see that layout file. When you look closely at the view tree, you can find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContentFrameLayout&lt;/code&gt;, the parent of your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FrameLayout&lt;/code&gt;. Android framework creates it internally and adds your views in it. It is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FrameLayout&lt;/code&gt; with a different name.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ContentFrameLayout&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FrameLayout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ContentFrameLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ContentFrameLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AttributeSet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ContentFrameLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AttributeSet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defStyleAttr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attrs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defStyleAttr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If that is almost the same, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FrameLayout&lt;/code&gt; in your layout file seems unnecessary. As you know, it is better to have a short view tree for the performance. You can do it with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;merge&amp;gt;&lt;/code&gt; tag. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;merge&amp;gt;&lt;/code&gt; tag is designed to eliminate redundant view groups. Android framework places views in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;merge&amp;gt;&lt;/code&gt; tag directly into the parent layout. The layout file can be changed like this.&lt;/p&gt;

&lt;p&gt;Since the parent layout is used, you can remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout_width&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layout_height&lt;/code&gt; attributes. Actually, any attributes in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;merge&amp;gt;&lt;/code&gt; tag are just ignored even though you set.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;merge&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:android=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://schemas.android.com/apk/res/android&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_gravity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;center&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:textSize=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;20sp&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Button&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wrap_content&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:layout_gravity=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bottom|center&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;android:text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Button&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;/merge&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/03-20/layout-inspect-content-frame-layout.png&quot; alt=&quot;layout-inspect-content-frame-layout&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;A shorter view tree brings better performance in Android. Android frame supports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;merge&amp;gt;&lt;/code&gt; to eliminate redundancy view groups. It is useful especially when you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FrameLayout&lt;/code&gt; as a root view. With that, you can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ContentFrameLayout&lt;/code&gt; directly.&lt;/p&gt;
</description>
        <pubDate>Wed, 20 Mar 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/03/20/use-the-merge-tag-for-optimizing-view-tree.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/03/20/use-the-merge-tag-for-optimizing-view-tree.html</guid>
        
        
      </item>
    
      <item>
        <title>How to Set Default Values in Room Database</title>
        <description>&lt;p&gt;When you initialize your application, you often need a default value to determine how it works. For example, most values of Settings require a default value. When you use a database, you read a value from there. Thus, it is better to put a default value in there instead of in the code.&lt;/p&gt;

&lt;p&gt;How can you do it? Room database supports a callback method. There are two callbacks: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onCreate&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onOpen&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onCreate&lt;/code&gt; is called only when the database is created for the first time. After that, this is not called again. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onOpen&lt;/code&gt; is called when the database is opened. Both callbacks are not called when your application is started but called when your code accesses the database such as querying.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Callback&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@NonNull&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SupportSQLiteDatabase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@NonNull&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SupportSQLiteDatabase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;If you want to pre-populate data only one time, you can do it using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onCreate&lt;/code&gt; callback. However, it wouldn’t fit well if there is a chance to add another default value later. If you think about Settings, there could be a new setting option in the next version.&lt;/p&gt;

&lt;p&gt;When the application is restarted, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onOpen&lt;/code&gt; can be called unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onCreate&lt;/code&gt;. Now the remaining question is how to set default values properly. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onOpen&lt;/code&gt; can be called several times, you need to pre-populate data only if it is necessary. If not, you could end up overriding data changed by a user.&lt;/p&gt;

&lt;p&gt;This sounds like a bit tricky but actually quite simple to do. Room database supports to select a conflict algorithm. By selecting, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFLICT_IGNORE&lt;/code&gt;, you can set default values without worrying overriding. Room database doesn’t allow to access the database on the main thread unless you set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowMainThreadQueries()&lt;/code&gt;. Thus, the callback method is executed not on the main thread.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AppDatabase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;database&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Room&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;databaseBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AppDatabase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;database.db&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addCallback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RoomDatabase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@NonNull&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SupportSQLiteDatabase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultMaps&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;defaultMaps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;theme&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dark&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;defaultMaps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto_play_mode&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;defaultMaps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;shuffle_mode&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultMaps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;entrySet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;ContentValues&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ContentValues&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Setting&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SQLiteDatabase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CONFLICT_IGNORE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Fri, 15 Mar 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/03/15/how-to-set-default-values-in-room-database.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/03/15/how-to-set-default-values-in-room-database.html</guid>
        
        
      </item>
    
      <item>
        <title>Android: Analyze Stack Trace from Plain Text Log</title>
        <description>&lt;p&gt;A stack track is a report that shows the stack frames at a certain point. When you debug your application, this is useful to know how to this method is called. This is even useful when a crash happens. At that time, you need to know what happened. A stack track can show how to end up having a crash. By analyzing it, you can find the root problem in your application.&lt;/p&gt;

&lt;p&gt;When you have a crash issue while developing, you can see it in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Logcat&lt;/code&gt; tab in Android Studio. In the log, there are blue and grey texts, which tell you the file and line information on that stack frame. The blue means that stack frame is in your source code. Whereas, the grey means that it is in a third-party library or framework code. By clicking it, you can easily navigate.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/03-10/crash-log.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Crashes can happen not only when you are using Android Studio but also when anytime. Someone can report an issue with a log. Or, you can see them on the crash reporting tool such as Fabric. For both cases, you will see the plain text log like below since that didn’t happen in the Android Studio.&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display:block; text-align:center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-4117634760413699&quot; data-ad-slot=&quot;8949905098&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NullPointerException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Attempt&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invoke&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;todoapp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;todoapp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addedittask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;AddEditTaskPresenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createTask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AddEditTaskPresenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;142&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;todoapp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addedittask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;AddEditTaskPresenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;saveTask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AddEditTaskPresenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;todoapp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addedittask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;AddEditTaskFragment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;$onActivityCreated&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AddEditTaskFragment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;From this log, you can navigate the file and line manually and one by one. If you want to see a below stack frame, you can open another file and go to that line. This is absolutely doable but a bit cumbersome. When a crash happens while developing, it is really easy to navigate since you just need to click. For that plain text log, Android Studio supports to convert it clickable after parsing. Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Analyze &amp;gt; Analyze Stack Trace...&lt;/code&gt; menu.  Then, paste the log and click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OK&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/03-10/analyze-stack-trace.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The parsed stack trace will be shown and you can now easily navigate. If you analyze the plain text log a lot, you can turn on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Automatically detect and analyze&lt;/code&gt; option. With that, Android Studio show the parsed stack trace without opening the menu.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/03-10/parsed-stack-trace.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 10 Mar 2019 00:00:00 +0000</pubDate>
        <link>http://sangsoonam.github.io/2019/03/10/android-analyze-stack-trace-from-plain-text-log.html</link>
        <guid isPermaLink="true">http://sangsoonam.github.io/2019/03/10/android-analyze-stack-trace-from-plain-text-log.html</guid>
        
        
      </item>
    
  </channel>
</rss>
