LAMBDA EXPRESSIONS IN ANDROID ( PART III )


I talked about basics of lambda expressions and method references, which are among the new features introduced in Java 8, in part I and part II of this series. Remember, not all the new features of Java 8 are available in Android. In this final part, I am going to explain about what changes you all have to make in build.gradle file , for using the two features in Android. The two features are supported in every version of Android, given that you make following changes on your build.gradle file

apply plugin: 'com.android.application'
//Android 1.0.0+ Gradle plugin
//as it contains DSL for jackOptions
android {
  compileSdkVersion 24
  //build tool version  21.1.1 and above
  // as it contains jack compiler
  buildToolsVersion "24.0.1"
  defaultConfig {
    applicationId "com.wordpress.laaptu.lambdawithandroid"
    //other stuff
    //jack compiler is needed if we are going to work with Java 8 features
    jackOptions.enabled true
  }
 //we need to specify that we are interested
 //in using Java8 features in compileOptions
  compileOptions {
    targetCompatibility 1.8
    sourceCompatibility 1.8
  }
}

This is all required , for you to work with lambda expression and method reference features in Android. You can check up this github link for the samples that use the two features of Java 8.  This is all for lambda expression in Android and do check upon following references for more

References

Lambda Expressions In Android ( Part II )


In Part I, I wrote the basics of lambda expression. I am going to write a little about what other methods that can be added to the interface definition (functional interfaces ) and method reference feature of Java 8.

Lambda expression is for interface with only one defined method. If there is other methods to be added on that interface, it will be default and static method definition and implementation only. Look at this link to know more. To illustrate this with example, let us take an interface

public interface IPrintStore {
    void  printName(String s);
}

Now we can easily write a lambda expression for this as

IPrintStore iprintStore = (s) ->
     System.out.println(String.format("You need to print this name =%s", s));
iprintStore.printName("Lambda");

We can only add and implement methods with modifiers default and static as in following example

public interface IPrintStore {
    void printName(String s);
    default void storeName(String s) {
        System.out.println(String.format("Store this %s to database", s));
    }
    public static String addExtraName(String s) {
        String value = s.concat(" :This is extra");
        return value;
    }
}

And use in the following manner

IPrintStore iprintStore = (s) ->
    System.out.println(String.format("You need to print this name =%s", s));
iprintStore.printName("Lambda");
iprintStore.storeName("Lambda");

This is all for functional interfaces in Java 8 and now let us focus on method reference feature of Java 8. As mentioned in Part I, lambda expression is only concerned with method signature ( arguments ) and method implementation ( code block )  of interface having a single method implementation. Method reference also works in similar manner and just like lambda , it is also concerned with arguments, code block and return type of a function.

 

screen-shot-2016-09-09-at-2-00-12-pm

Let’s take a simple analogy ( please don’t jumble up this example with classes and objects ). In order to be a mail man, a person needs to have a hair and a pair of shoes. So, all the person who has a hair and a pair of shoes can be treated as a mailman and those person would readily do the job of mailman.

Screen Shot 2016-09-09 at 4.33.30 PM.png

Now let us move this analogy, to our interface and it’s implementation. Let us create a simple interface named ICombine as

interface ICombine {
    void combine(int age, String name);
}

 

Let us analyze the method definition and signature or to say let us define the criteria which determines whether a function can be treated as object of ICombine

screen-shot-2016-09-15-at-11-12-53-am

 

So, just like mailman analogy, any instance method or static method having same return type or arguments as that of ICombine interface method, it can be treated as objects of ICombine.  So our criteria is a function should have void return type and should take two arguments where first argument must be of type int and second argument must be of type String. So, any method matching this criteria can be taken as ICombine’s object. Take a look at following illustration for it

Screen Shot 2016-09-15 at 11.00.08 AM.png

 

Let us now construct a class having a public and a public static method as

public class MethodReferenceDemo {
    public void methodReferenceInstance(int age, String someName) {
        System.out.println("methodReferenceInstance -----");
	 String value = someName.concat(" age = ").concat(String.valueOf(age));
	 System.out.println("combined value :: " + value);
    }

    public static void methodReferenceStatic(int someInt, String someString) {
        System.out.println("methodReferenceStatic -----");
	String value = someString.concat(" age =
        ").concat(String.valueOf(someInt));
	System.out.println("combined value :: " + value);
    }
}

Here methods methodReferenceInstance and methodReferenceStatic both have same arguments and return type as that of ICombine’s combine method. So, method reference feature of Java 8, can be used to treat the two methods as ICombine’s object in following manner

ICombine combine;
// without method reference
combine = new ICombine() {
    @Override
    public void combine(int age, String name) {
        System.out.println("without method reference---------");
	String value = name.concat(" age = ").concat(String.valueOf(age));
	System.out.println("combined value :: " + value);
    }
};
combine.combine(40, "Middle age guy");
// with method reference
System.out.println("with method reference-----------");
MethodReferenceDemo demo = new MethodReferenceDemo();
combine = demo::methodReferenceInstance;
combine.combine(100, "Old Guy");
combine = MethodReferenceDemo::methodReferenceStatic;
combine.combine(25, "Young Guy");

So, this is all, in method reference feature of Java 8. Hope , you all clearly understood on how it can be used. Look upon these github samples to know more about it.  In part III, I will simply talk about what changes are to be made in Android , for these features to be used.

Lambda Expressions In Android ( Part I )


One of the many  new features introduced in Java 8, this blog post is focused on lambda expression and method reference. Let’s be clear that Android doesn’t support all the new features of Java 8, but only a subset of new features of Java 8.

So, what is lambda expression then? Before, going into nitty gritty of lambda, let us understand it by an analogy. Lambda is simply a short hand notation. Let us take a scenario. There is a mailman who takes a written command. As per the command, the mailman performs certain task. To save time on writing long commands, both command and mailman is now modified to understand short commands. Take a look at following picture

Screen Shot 2016-09-09 at 1.10.29 PM.jpg

Here, previously the long form As Soon As Possible is now reduced into its short form as ASAP. Under the hood, the mailman interprets ASAP as As Soon As Possible and does the task accordingly. So, the one who is writing the command, it will be easier to write short commands.Under the hood, the whole process works same as before.

So, lambda being a short hand notation, makes the coder easier to write down short codes instead of long ones. Lambda expression is used as a short hand notation for anonymous classes with simple implementation i.e. interface definition with only one method. Rather than getting into jargons and definition, let us illustrate this by a simple example

interface IPrint {
		void printName();
}

And to use, this interface, we need to do

IPrint print;
print = new IPrint() {
   @Override
   public void printName() {
       System.out.println("Print without lambda");
   }
};
print.printName();

During this whole process, the most important part is functional implementation of IPrint  i.e  printName() implementation i.e.

public void printName() {
       System.out.println("Print without lambda");
}

This is simply a function, and in a function the most important part are return type, arguments, block of code

Screen Shot 2016-09-09 at 2.00.12 PM.png

Lambda expression is typically shorthand notation for arguments, code block and return type. Let us assume, that we are now concerned with only important part and now we want to write what is important only and scrap out unnecessary parts. Now constructing the same function in short hand notation ( without any lambda expression)

public void printName() {
       System.out.println("Print without lambda");
}
//it's short hand notation be
void (){
   System.out.println("Print without lambda");
}
//we know that if any function returns something, we need to add return statement
//and any function that doesn't return anything, no return statement
//so again the short hand notation be like
(){
  System.out.println("Print without lambda");
}

At this point, don’t get confused where the function name went and all those stuff, just assume we are very busy coders and we want only important stuff of any function definition. Let us look into more examples

IMG_20160909_144828.jpg

Lambda expression is only concerned with method signature ( arguments) and method implementation ( code block) , and provides the short hand notation based upon that. So, the shorthand notation, with lambda expression would be now

img_20160909_150002

Remember, lambda expression is only for interface having single method, implementation. And in order to write lambda expression, you need to know the interface and its method, and then write the short hand notation based upon it. So our interface IPrint will now become

IPrint print;
//without lambda
print = new IPrint() {
    @Override
    public void printName() {
        System.out.println("Print without lambda");
    }
};
print.printName();
//with lambda
print = () -> System.out.println("Print with lambda");
// or
print = () -> {
    System.out.println("First print with lambda");
    System.out.println("Second print with lambda");
};

Let’s see other implementation, an interface having a return type

interface IPrint {
    String printName();
}
IPrint print;
//without lambda
print = new IPrint() {
    @Override
    public String printName() {
        String value = "Without lambda";
	System.out.println(value + " -------------");
	return value;
    }
};
//with lambda
print = () -> System.out.println("With lambda");
print = () -> {
    String value = "With lambda again";
    System.out.println(value + " -------");
    return value;
};

Another implementation where an interface has arguments and return type

interface IPrint {
    int printName(int age, String name);
}
IPrint print;
//without lambda
print = new IPrint() {
    @Override
    public int printName(int age, String name) {
        System.out.println("Without lambda--------");
	System.out.println("Your name = " + name);
	System.out.println("Your age = " + age);
	return age * 10;
    }
};
//with lambdas
//notice the arguments name can be any and type definition not required
print = (a, b) -> {
    System.out.println("With lambda--------");
    System.out.println("Your name = " + b);
    System.out.println("Your age = " + a);
    return a * 20;
    };

print = (int age, String name) -> {
    System.out.println("With lambda again --------");
    System.out.println("Your name String value = " + name);
    System.out.println("Your age int value = " + age);
    return age * 30;
    };

Remember there is no performance gain by writing short hand notation. Lambda is simply ease of writing codes and is concerned with short hand form of method signature and method implementationscreen-shot-2016-09-09-at-3-19-18-pm

Here is the github link which contains, all the examples mentioned in this blog post. In part II I will talk  about method reference feature of Java 8 and finally how we can use these features in Android.

Write your own Android Authenticator


udinic

When I wrote Any.DO’s sync system, about 18 months ago, I wanted to use the built in AccountManager API to authenticate and store the users’ credentials. When I used it to access Google accounts it seems a pretty simple experience, so I thought I should do that for Any.DO as well. It also goes very well with a sync mechanism (using a SyncAdapter), making it the perfect solution. The problem – no good documentation was out there. The developers community didn’t have much experience with that back then, and since we didn’t have much time to figure out issues that could arise from this “No man’s land”, a decision was made to use other methods.

But times have changed..

I recently studied that feature again for a project I’m working on, and saw there’s a huge improvement with the knowledge about it. Besides the better documentation on the Android.com site,

View original post 2,889 more words

Android View Basics: Coordinates,Margin,Padding,Dip,Px



In this post,I am going to go for the basics of Android Views like its co-ordinates,difference between margin and padding and what is dip and conversion from dip to px and vice versa. In order to proceed,let’s first get some understanding about Android device Screen Size and Screen Density. For these two terms, I will take help from Supporting Multiple Screens

  1. Screen Size: This is simply the width and height of the device rectangular screen. So,when we say 480×800 device,we are referring to the screen size whose width = 480 px and height =800 px


  2. 480x800 screen

  3. Screen density: It means how many pixels are present in a given area of the screen. Let’s say we have 1 square inch of area (i.e. width=1 inch and height =1 inch) on 480 x 800 screen size device. The number of pixels on that 1 square inch of area determines the density of pixels. If that 1 square inch of area holds more number of pixels,then that screen has high density. Meaning greater the number of pixels,the greater is its density and if lower the number of pixels,lower its density . Look at the picture below to understand the concept visually (taken from BBC site ). This indicates that 480×800 device can be ldpi,mdpi or hdpi as per its screen density . But, if screen size is large,then large pixels can be accommodated compared to small screen size devices.
  4. pixel-density-1


Let us know more about dip now.
dip: We all know that Android devices comes with different density and screen sizes. While giving View attributes like layout_width,layout_height,layout_margin,padding etc we use values with dip unit. So when we say android:layout_width=45dip and android:layout_height=45dip,we are drawing a view with 45 width and 45 height. The analogy which I am going to present is not accurate,but it helps in understanding dip concept. Say to draw 45 width line 45 pixels is needed.And if there was no dip ,then on higher density device the width seems smaller( as more pixels are found in a given area) but on lower density the width seems larger( as less pixels are found in a given area). Take a look at the picture below where there is not dip usage

View without dip consideration


Now when we use dip values,Android automatically takes screen density into consideration and then distributes the value as per the density, such that the view appears more or less similar in all the screens. Take a look at the picture below where there is dip usage.

View with dip consideration

Now comes the role of px.Whatever value in dip we represent,it has to be converted on actual screen unit or pixel. So px is the actual dimension that a view holds in screen. This conversion is handled by Android system. Meaning ,whatever we write in dip,it will convert those values to its relevant px unit,so that it could be drawn on the screen.For this,it takes the screen density into consideration.

If you write 5 dip,its pixel value will be different on different screen density.Using online dp to px calculator ,we get following px values for 5 dip on different screen densities
dp to px calculator


If you want to look upon the formula involved for dp to px conversion and vice versa ,you can look upon this conversion gist
Just check view.getWidth() or view.getHeight() ,it will give you different values than that, you have written on your layout.xml. Meaning,if you have given width and height as 45 dip on your layout.xml file,then calling view.getWidth() or view.getHeight() ,you will receive their respective px values.

Let’s now focus on to Android View Co-ordinates.In Android ,all the co-ordinates will be represented on px values. Android Screen as well as its view coordinates origin is (0,0) i.e. it starts from top left corner. Moving right from origin is positive X-axis and moving down from origin is positive Y-axis. Take a look upon the figure below

Screenshot from 2013-12-10 16:39:29

Screenshot from 2013-12-10 16:34:54


Let us take a following

 
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/firstLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/secondLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        android:background="@color/color_yellow">

        <ImageView
            android:id="@+id/firstImageView"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:layout_margin="5dip"
            android:background="@android:color/darker_gray"
            android:padding="5dip"
            android:src="@drawable/ic_launcher" />

        <ImageView
            android:id="@+id/secondImageImageView"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:background="@android:color/black"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>

    <ImageView
        android:id="@+id/thirdImageView"
        android:layout_width="48dip"
        android:layout_height="48dip"
        android:src="@drawable/ic_launcher"
        android:background="@android:color/black" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        android:id="@+id/thirdLayout"
        android:background="@color/color_orange">

        <ImageView
            android:id="@+id/fourthImageView"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:src="@drawable/ic_launcher"
            android:background="@android:color/darker_gray" />

        <ImageView
            android:id="@+id/fifthImageView"
            android:layout_width="48dp"
            android:layout_height="48dip" 
            android:src="@drawable/ic_launcher"
            android:background="@android:color/black"/>
    </LinearLayout>
</LinearLayout>
  

I am making all the test on my Samsung Galaxy S I8262 device which has a screen size of 480×800 px and screen density of 240 dpi. So, the values which I illustrate on px is equivalent to this device only and you may yield different values of px on your devices. If you look upon the layout.xml,I have used mainly two dip values, 48dip and 5dip. The respective value of them in px is 48dip=72px and 5dip=8px. So ,let us now calculate,the co-ordinate of each of the views. For that we must understand these terms view.getLeft(),view.getRight(),view.getTop(),view.getBottom(). These values are always taken in reference to their parent i.e. how far to the left and bottom of the viewgroup/parent is the view lying.Look upon the figure below
Screenshot from 2013-12-11 17:33:45
Figure A
Screenshot from 2013-12-11 19:19:18
Figure B
Screenshot from 2013-12-12 14:16:28
Figure C
Looking at the figure above,following points can be gathered

1) getLeft() : distance between leftmost edge of parent and leftmost edge of view
2) getRight(): distance between leftmost edge of parent and rightmost edge of view
3) getTop(): distance between topmost edge of parent and topmost edge of view
4) getBottom(): distance between topmost edge of parent and bottom most edge of view
5) View position or location inside parent: (getLeft(),getTop())
6) view width = getRight()-getLeft()
7) view height = getBottom()-getTop()

Look at Figure B and note down firstLayout getRight() and getBottom() values. We have 480×800 px screen,and firstLayout is our main layout, which has the freedom to occupy whole screen(look upon layout.xml). Here getRight()=480px and getBottom=690px. firstLayout fills entire screen and its width value equals width of screen. But is height=690px-0px != 800px. I am not running this sample on fullscreen mode,so while launching the app,I will have status bar and ActionBar (if I am running on Android 3.0 and above or if I am using ActionbarSherlock). In my case,I have both status bar and ActionBar. These two views also take portion on screen and in my case I am using portrait mode ,where status bar height=38px and actionbarHeight=72px. So

firstLayout getBottom() = screenHeight()-(status bar height+action bar height)
=800 -(38+72)
=690px


Look at the following figure,to understand more.
Screenshot from 2013-12-12 17:04:48
But If I had run my app on fullScreen mode,then firstLayout height would have been 800px. For calculating status bar height and action bar height,you can refer to following gists
status bar height:
action bar height:

getLeft(),getTop() gives view's position inside parent/viewgroup co-ordinates. But If you want to get the position or location of view in the screen you have to use

 int[] xy = new int[2];
 view.getLocationOnScreen(xy);
 int xPosition =xy[0];
 int yPosition= xy[1];						

Screenshot from 2013-12-12 16:40:25
I hope,all the explanation gives you idea about Android View Co-ordinates .
Lastly, I want to briefly explain about Margin and Padding . Consider the following

  <LinearLayout
        android:id="@+id/secondLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        android:background="@color/color_yellow">

        <ImageView
            android:id="@+id/firstImageView"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:layout_margin="15dip"
            android:background="@android:color/darker_gray"
            
            android:src="@drawable/ic_launcher" />

        <ImageView
            android:id="@+id/secondImageImageView"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:padding ="10dip"
            android:background="@android:color/black"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>

which is visually seen as
Screenshot from 2013-12-12 17:22:38
Here both ImageView has width and height of 48 dip. firstImageView has layout margin=15dip and secondImageView has padding =10dip . By adding padding/margin , the view height and width remains same,there won’t be any change. While doing margin ,the view will be moved margin distance to left,right,top or bottom within parent view . So, while accessing view margin programmatically ,you have use view layoutParams . When we do padding, the view moves its content (in our case the ImageView src) to padding distance to left,right,top or bottom within the view itself. Maybe the pictorial representation,above would highlight this.
This is all,for now and if you are reading this,then probably you haven’t slept while reading this long blog list. The main reason,I wrote this post is that,I wanted to visually represent Android Co-ordinates and make understand basics of dip,px,margin,padding .
If you want to find out by yourself,the dimension represented on the figure(though value may differ as per screen density),you can play with this source at laaptu’s github.
Till next time have fun and enjoy😉

How to check whether your push notification/GCM message receive logic on app is working or not



In this post,I am not trying to teach the basics of GCM/push notification.You can easily get started with GCM from Android GCM. This post is for those developers who have

  • Successfully registered their device to GCM server and received GCM phone registration id
  • Implemented the logic to receive notification from their server
  • and are relying on back end developers to send test notification message


Frankly speaking I am writing this post out of frustration of dealing with back end developers who simply say that app logic is not right but back end is error proof.And they constantly force us to check our code. So,in this case if any back end developer say that their process of sending push notification to app is right and you also feel that your logic is right,then simply test your logic with HTTP post request.For this purpose I am using a Chrome app named Dev Http Client,which is BTW great great tool for any app developer doing REST API.I assume you have done the following

  1. Created a Google Project on Google API console
  2. Activated Google Cloud Messaging for Android service on that project
  3. Created an API key for that project,so that Google API can be accessed using this key
  4. And all the procedures I have described in above list


Now carefully look upon the following images

01_notification_format

01_notification_msg


So,on above image you see that you have to put

  1. Google API console API key on header
  2. Phone registration id on body part
  3. On data you have to put what kind of message you want to pass
  4. Press Send button to send the push notification


You can see the message response on second picture i.e. what have been sent by Google GCM server. So,if you receive the notification using above procedure,your app logic is right otherwise you have to make some changes. Further,to simply check whether your GCM/push notification receive logic is working or not,you don’t have to rely on back end developers,you can do on your own.

If you have any questions on this,feel free to ask me on comments.Till then Happy KitKat (as KitKat along with Nexus 5 was released yesterday)😉

Android update app widget with ListView after phone reboot



This tutorial is followup of previous tutorial of mine named Android Showing Remote Image on ImageView of App-Widget ListView. If you look upon the WidgetProvider.java class,I haven’t included any functional statement on onUpdate() method except super.onUpdate(context,appWidgetManager,appWidgetIds).


I have stated earlier that onUpdate() method is called on every update interval that is set on appwidget-provider xml file( in our case xml/widgetinfo.xml) and on every phone bootup. So, in our case as there is no functional statement on onUpdate() method, our widget will be blank after phone reboot or on phone start.If one includes,update logic on onUpdate() method of appwidget,then there is no need to care about phone reboot. But in our case we need to address phone reboot/start issue as our appwidget will be blank after phone reboot/start.


I will first point out the logic,I am going to implement on this tutorial

  1. Find out phone boot completion using BroadCastReceiver and listening to android.intent.action.BOOT_COMPLETED intent
  2. Then on appwidget provider simply update the appwidget
  3. I am just using a boolean value,but one can send custom broadcast to appwidget provider,notifying about phone boot completion and making necessary updates out there


Let’s create our BroadcastReceiver to listen to phone boot completed broadcast.

public class PhoneBootCompleteReceiver extends BroadcastReceiver {

	public static boolean wasPhoneBootSucessful = false;

	/**
	 * Just changing the boolean value on Phone Boot Complete event one can send
	 * custom broadcast from here as well send these broadcast of appwidget
	 * provider to make necessary updates
	 */
	@Override
	public void onReceive(Context context, Intent intent) {
		if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
			wasPhoneBootSucessful = true;
		}
	}
}


For this PhoneBootCompleteReceiver to work,one must include following on their manifest.xml file.

<!-- Permission to receive boot completed intent or broadcast -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<!-- Broadcast receiver that responds when phone successfully boots -->
        <receiver android:name=".PhoneBootCompleteReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>


Now moving on the our appwidgetprovide class i.e.WidgetProvider,following changes are to be made

	/*
	 * this method is called every 30 mins as specified on widgetinfo.xml this
	 * method is also called on every phone reboot so on phone reboot,we need to
	 * once again update the widget i.e populate the listview of the widget
	 */
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {

		if (PhoneBootCompleteReceiver.wasPhoneBootSucessful) {
			PhoneBootCompleteReceiver.wasPhoneBootSucessful = false;
			final int N = appWidgetIds.length;
			for (int i = 0; i < N; i++) {
				RemoteViews remoteViews = updateWidgetListView(context,
						appWidgetIds[i]);
				appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
			}
		}

		super.onUpdate(context, appWidgetManager, appWidgetIds);
	}


This is all one has to do, in order to update appwidget on phone startup. All these tutorials of AppWidget ListView is to show the basics of appwidget containing ListView,along with procedure to fill up data from remote or web.


One important thing I want to mention is that, while implementing own update interval i.e. not relying upon update interval set at appwidget-provider.xml,one has to use appWidgetManager.notifyAppWidgetViewDataChanged() instead of appWidgetManager.updateAppWidget(). This alone doesn’t change the data of the ListView.This process calls onDataSetChanged() of RemoteViewsFactory. So at onDataSetChanged,you have to again fetch data that is supplied to RemoteViewsFactory. Then only,the changed data is reflected upon appwidget ListView.


Finally,you can download the whole source code from my github. Till next time,enjoy coding😉