How to Create a Tracker For Cryptocurrency On Android By Using Kotlin
Hello to everyone, and today folks we are presenting a short but
a very useful tutorial where you will learn the following:
- How to Get Queries with Retrofit
- Retrofit and Rx
- RecyclerView with Kotlin
- How you can retrieving a data from API
Introduction
Let’s forget how to include support for Kotlin and other obvious and understandable things, like creating a project. We will use this api
Setting Up a Manifest
In order to make requests you need to have permission to use the network:
<uses-permission android:name="android.permission.INTERNET"/>
Adding libraries to the Gradle
We need Retrofit and RxAndroid.
//Retrofit compile "com.squareup.retrofit2:retrofit:2.3.0" compile "com.squareup.retrofit2:adapter-rxjava2:2.3.0" compile "com.squareup.retrofit2:converter-gson:2.3.0" //RxAndroid compile "io.reactivex.rxjava2:rxandroid:2.0.1"
Creating layouts
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.kram.vlad.cryptocurrency.activitys.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.constraint.ConstraintLayout>
RecyclerView must know what its elements look like for this we need to create item.xml.
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/ic_launcher_background"/> <TextView android:id="@+id/symbol" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginStart="11dp" android:layout_marginTop="11dp" android:layout_toEndOf="@+id/imageView" android:text="TextView" android:textColor="@android:color/black" android:textSize="18sp" android:textStyle="bold"/> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/symbol" android:layout_marginStart="11dp" android:layout_toEndOf="@+id/symbol" android:text="|" android:textColor="@android:color/black" android:textSize="18sp"/> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/textView2" android:layout_marginStart="12dp" android:layout_toEndOf="@+id/textView2" android:text="TextView" android:textColor="@android:color/black" android:textSize="14sp"/> <TextView android:id="@+id/money" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/name" android:layout_alignParentEnd="true" android:layout_marginEnd="13dp" android:text="TextView" android:textColor="@android:color/black" android:textSize="14sp" android:textStyle="bold"/> <TextView android:id="@+id/textView6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/imageView" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp" android:layout_toEndOf="@+id/imageView" android:text="24h:"/> <TextView android:id="@+id/textView7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/textView6" android:layout_alignBottom="@+id/textView6" android:layout_alignEnd="@+id/name" android:text="7d:"/>
Making a model for parsing the answer
For such purposes, a POJO generator is a good idea.
data class ResponseItem(@SerializedName("id") @Expose var id: String?, @SerializedName("name") @Expose var name: String?, @SerializedName("symbol") @Expose var symbol: String?, @SerializedName("rank") @Expose var rank: String?, @SerializedName("price_usd") @Expose var priceUsd: String?, @SerializedName("price_btc") @Expose var priceBtc: String?, @SerializedName("24h_volume_usd") @Expose var _24hVolumeUsd: String?, @SerializedName("market_cap_usd") @Expose var marketCapUsd: String?, @SerializedName("available_supply") @Expose var availableSupply: String?, @SerializedName("total_supply") @Expose var totalSupply: String?, @SerializedName("max_supply") @Expose var maxSupply: String?, @SerializedName("percent_change_1h") @Expose var percentChange1h: String?, @SerializedName("percent_change_24h") @Expose var percentChange24h: String?, @SerializedName("percent_change_7d") @Expose var percentChange7d: String?, @SerializedName("last_updated") @Expose var lastUpdated: String?) {
Create a simple get query
We will use Rx so our Get function should return Observable. Also right here we create Factory, with it we will receive the Retrofit object.
interface RetrofitGetInterface { @GET("v1/ticker/") fun getCryptocurrency(): Observable<List<ResponseItem>> companion object Factory { fun create(): RetrofitGetInterface { val retrofit = Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) // telling what we are parsim here .baseUrl("https://api.coinmarketcap.com/") // the basic part of the link .build() return retrofit.create(RetrofitGetInterface::class.java) } } }
Now making a request
For queries, we will use Rx. If you are not familiar with reactive programming – you definitely have to learn it.
val apiService = RetrofitGetInterface.create() apiService.getCryptocurrency() .observeOn(AndroidSchedulers.mainThread())// telling in which stream to return .subscribeOn(Schedulers.io()) // Choose io - to work with data and the Internet .subscribe({ result -> arrayListInit(result) // Here is callback }, { error -> error.printStackTrace() })
Make an adapter for the list
class RecyclerViewAdapter(private val result: List<ResponseItem>, val resources: Resources):RecyclerView.Adapter<RecyclerViewAdapter.CardViewHolder>()
The data that we received from our request should be shipped in some array (List) ResponseItem. It needs to be transferred to the adapter so that it fills our list.
In GetItemCount, we must return the size of the array so that the adapter knows how many elements will be on our list.
override fun getItemCount() = result.size // Return the size of the data array
In OnCreateViewHolder we need to inflate the layout of our item.
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): CardViewHolder { return CardViewHolder(LayoutInflater.from(parent?.context) .inflate(R.layout.item, parent, false)) // Tell the RecyclerView how the item should look }
All the time in the code some CardViewHolder is lit. It must fill the views of each item with data from an array.
class CardViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) { fun bind(result: List<ResponseItem>, position: Int, resources: Resources) { val responseItem: ResponseItem = result.get(position) itemView.symbol.text = responseItem.symbol itemView.name.text = responseItem.name ... } }
The bind function takes all necessary data and fills them with views. We address this function to onBindViewHolder. And thanks to the syntax of the language we do it quite nicely.
override fun onBindViewHolder(holder: CardViewHolder, position: Int) = holder.bind(result, position, resources)
The last step: we attach our adapter
For this, you just need to write in the callback:
recyclerView.adapter = RecyclerViewAdapter(result, resources) recyclerView.layoutManager = LinearLayoutManager(this)
The tutorial came out pretty short and simple, so there was not much explanation, but hope you like it.