+4

Demo ứng dụng xem tin tức sử dụng kotlin và retrofit

Giới thiệu về kotlin

Như các bạn cũng biết, vào ngày 17 tháng 5 năm 2017, tại sự kiện thường niên của Google dành cho các lập trình viên, có tên là Google I/O, đội ngũ Android của công ty này đã công bố rằng ngôn ngữ lập trình mới Kotlin sẽ chính thức lên ngôi thay thế cho người tiền nhiệm Java “cũ rích”. Họ còn đưa ra các dẫn chứng cho thấy rằng Kotlin là một ngôn ngữ mạnh mẽ, trực quan, an toàn và ngắn gọn hơn Java – Một ngôn ngữ mà mọi lập trình viên đã từng buộc phải sử dụng để viết các ứng dụng Android của họ trước đây.

Từ đó trở đi, Kotlin đã trở thành một ngôn ngữ rất hot. Nhà nhà nghiên cứu Kotlin, người người nghiên cứu Kotlin. Một số công ty lớn như Uber, Nexflix, Trello, Pinterest,… cũng đã nhanh chóng sử dụng Kotlin, bên cạnh các ngôn ngữ khác của họ. Cũng không thể phủ nhận rằng, Kotlin ra đời không những vừa giúp các lập trình viên Android sử dụng Java cũ có cơ hội được học hỏi và nâng cấp kiến thức, nâng cấp sản phẩm của họ, mà còn giúp cho các bạn nào dự định làm quen với lập trình Android có một chọn lựa hiệu quả hơn về một ngôn ngữ chính thức dành cho hệ điều hành này

Viết ứng dụng xem tin tức sử dụng kotlin và retrofit

Link API: http://dev.2dev4u.com/news/api.php?latest_news=10

  1. implement các thư viện cần sủ dụng trong gradle
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:26.0.1'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
    implementation 'com.android.support:design:26.0.1'
    implementation 'com.github.bumptech.glide:glide:3.7.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.0'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.0'
}
  1. Giao diện màn hình chính ( chỉ có RecyclerView để hiển thị list bài post): activity_main.xml
<?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.example.duong.appnews.MainActivity"
    >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</android.support.constraint.ConstraintLayout>

  1. Giao diện mỗi item hiển thị bài post: item_post.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="4dp"
    >

    <ImageView
        android:id="@+id/imgThumbnail"
        android:layout_width="130dp"
        android:layout_height="110dp"
        android:scaleType="centerCrop"
        />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="2dp"
        >

        <TextView
            android:id="@+id/text_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="3"
            android:textColor="#000"
            android:textSize="15dp"
            />
        <TextView
            android:id="@+id/text_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="3"
            android:textColor="#6b6868"
            android:textSize="13dp"
            />

        <TextView
            android:textColor="#182686"
            android:id="@+id/text_category"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            tools:ignore="RtlCompat"
            />

    </LinearLayout>
</LinearLayout>
  1. Tạo class Post
package com.example.duong.appnews.model

import com.google.gson.annotations.SerializedName

class Post {
  @SerializedName("id_post")
  var mId: Int = 0
  @SerializedName("id_ca")
  var mIdCa: Int = 0
  @SerializedName("name_ca")
  var mNameCa: String = ""
  @SerializedName("title")
  var mTitle: String = ""
  @SerializedName("description")
  var mDescription: String = ""
  @SerializedName("content")
  var mContent: String = ""
  @SerializedName("datetime")
  var mDatetime: String = ""
  @SerializedName("image")
  var mImage: String = ""

}
  1. Tạo class API Để sử dụng các yêu cầu mạng đến một RESTful API bằng Retrofit, chúng ta cần tạo ra một đối tượng bằng cách sử dụng lớp Retrofit Builder và cấu hình nó với một URL cơ sở.
package com.example.duong.appnews.Service

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory


object API {
  private var retrofit: Retrofit? = null
  val apiService: APIService
    get() {
      if (retrofit == null) {
        retrofit = Retrofit.Builder()
            .baseUrl("http://dev.2dev4u.com")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
      }
      return retrofit!!.create(APIService::class.java)
    }
}

  1. Tạo interface APIServices Tạo API Interface đặt tên là APIService. Interface này dùng để chứa các phương thức mà chúng ta sẽ sử dụng để gọi các yêu cầu truy vấn HTTP chẳng hạn như GET, POST, PUT, và DELETE.
package com.example.duong.appnews.Service

import com.example.duong.appnews.model.Post
import retrofit2.Call
import retrofit2.http.GET

interface APIService {
  @get:GET("/news/api.php?latest_news=10")
  val posts: Call<List<Post>>
}
  1. Tạo Adapter cho RecyclerView
package com.example.duong.appnews

import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide
import com.example.duong.appnews.model.Post

class PostAdapter(private val mContext: Context,
    posts: List<Post>) : RecyclerView.Adapter<PostAdapter.BookViewHolder>() {
  val mPosts: List<Post> = posts

  inner class BookViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val description: TextView = itemView.findViewById<TextView>(R.id.text_description)
    val category: TextView = itemView.findViewById<TextView>(R.id.text_category)
    val image: ImageView = itemView.findViewById<ImageView>(R.id.imgThumbnail)
    val title: TextView = itemView.findViewById<TextView>(R.id.text_title)
  }

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.item_post, parent, false)
    return BookViewHolder(view)
  }

  override fun onBindViewHolder(holder: BookViewHolder, position: Int) {
    val book = mPosts[position]
    holder.title.text = book.mTitle
    holder.description.text = book.mDescription
    holder.category.text = book.mNameCa
    Glide.with(mContext).load(book.mImage).into(holder.image)
  }

  override fun getItemCount(): Int {
    return mPosts.size
  }
}
  1. MainActivity
package com.example.duong.appnews

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.widget.Toast
import com.example.duong.appnews.Service.API
import com.example.duong.appnews.model.Post
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class MainActivity : AppCompatActivity(), Callback<List<Post>> {
  var mPosts: MutableList<Post> = mutableListOf()
  lateinit var recyclerview: RecyclerView

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    recyclerview = findViewById(R.id.recyclerview)
    recyclerview.layoutManager = LinearLayoutManager(this)
    recyclerview.adapter=PostAdapter(applicationContext, mPosts)
    initData()
  }

  fun initData(){
    API.apiService.posts.enqueue(this)
  }
  override fun onResponse(call: Call<List<Post>>?, response: Response<List<Post>>?) {
    if(response==null|| response.body()==null){
      return
    }
    mPosts.addAll(response.body()!!)
    recyclerview.adapter.notifyDataSetChanged()
  }

  override fun onFailure(call: Call<List<Post>>?, t: Throwable?) {
    Toast.makeText(applicationContext,"Error",Toast.LENGTH_SHORT).show();
  }

}
  1. Cấp quyền truy cập internet cho ứng dụng
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.duong.appnews">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>
  1. Kết quả

  2. Link source code cho bạn nào cần https://github.com/nguyenminhduong/AppNewKotlin/tree/master/AppNews

Cảm ơn các bạn đã theo dõi, chúc các bạn thành công với kotlin 😃


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí