Demo ứng dụng xem tin tức sử dụng kotlin và retrofit
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”. ...
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
Link API: http://dev.2dev4u.com/news/api.php?latest_news=10
- 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' }
- 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_awidth="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_awidth="match_parent" android:layout_height="match_parent"/> </android.support.constraint.ConstraintLayout>
- 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_awidth="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="4dp" > <ImageView android:id="@+id/imgThumbnail" android:layout_awidth="130dp" android:layout_height="110dp" android:scaleType="centerCrop" /> <LinearLayout android:orientation="vertical" android:layout_awidth="match_parent" android:layout_height="match_parent" android:padding="2dp" > <TextView android:id="@+id/text_title" android:layout_awidth="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_awidth="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_awidth="wrap_content" android:layout_height="wrap_content" android:textSize="15dp" tools:ignore="RtlCompat" /> </LinearLayout> </LinearLayout>
- 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 = "" }
- 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) } }
- 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>> }
- 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 } }
- 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(); } }
- 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>
-
Kết quả
-
Link source code cho bạn nào cần https://github.com/nguyenminhduong/AppNewKotlin/tree/master/AppNews