この記事へのリンク:https://blog.csdn.net/qq_40785165/article/details/109693263
みなさん、こんにちは。まだハゲになっていないプログラマーのシャオ・ヘイです~~~
あなたは楽に見えるように一生懸命働かなければなりません。
今日の記事は、Kotlinが以前に実行したインターフェースドッキングについて学習することです。使用されるネットワークデータ送信フレームワークはRetrofitであり、使用されるインターフェースはAndroidを再生するためのオープンインターフェースです。プロジェクトアドレス:https://gitee.com/fjjxxy/ kotlin_retrofit.git
知识体系下的文章
https://www.wanandroid.com/article/list/0/json?cid=60
方法:GET
参数:cid 分类的id,上述二级目录的id
页码:拼接在链接上,从0开始。
获取公众号列表
https://wanandroid.com/wxarticle/chapters/json
方法:GET
必要な権限
<uses-permission android:name="android.permission.INTERNET" />
依存関係を追加する必要があります
def retrofit_version = '2.6.1'
//----------------- retrofit begin -----------------
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version"
// ---- okhttp ----
implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
// ---- okhttp ----
//----------------- retrofit end -----------------
implementation 'androidx.recyclerview:recyclerview:1.0.0'
最初にレンダリングを見てください
レンダリングは2つのリストで構成されています。前のリストは最初のインターフェイスに接続され、次のリストは2番目のインターフェイスに接続されています。次はコード表示です。
(1)インターフェイスから返されたデータを受信するエンティティクラスResultを定義します
class Result<T> {
var errorCode: String? = null
var errorMsg: String? = null
var data: T? = null
}
(2)インターフェースApiを定義し、アノテーションを使用してRetrofitにRestfulスタイルのApiを提供します。さまざまなアノテーションの使用はここにはリストされていません。Baidu自身で行ってください。
interface Api {
/**
* 微信公众号列表
*/
@GET("wxarticle/chapters/json")
fun getwxarticle(): Call<Result<List<User>>>
/**
* 文章列表
*/
@GET("article/list/{page}/json")
fun getArticle(@Path("page") page: String, @Query("cid") cid: String): Call<Result<Article>>
}
(3)インターフェースリクエストツールクラスHttpHelperをカプセル化し、レトロフィットオブジェクトとApiサービスを取得し、インターセプターとプロセスログを設定します。コードは次のとおりです。
/**
* 接口请求工具类
*/
class HttpHelper {
companion object {
private val BASE_URL = "https://www.wanandroid.com/" //服务器地址
private var sHttpClient: OkHttpClient? = null
private var sApi: Api? = null
/**
* 添加拦截器,对返回的数据或者日志进行处理,对请求添加统一头部
*/
fun getHttpClient(): OkHttpClient? {
if (sHttpClient == null) {
synchronized(HttpHelper::class.java) {
if (sHttpClient == null) {
val builder = OkHttpClient.Builder()
//添加拦截器
var interceptor = HttpLoggingInterceptor(
HttpLoggingInterceptor.Logger { message ->
//对日志进行处理
Log.e("Tag", message)
}
)
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
builder.addInterceptor(interceptor)
builder.addInterceptor { chain ->
val request = chain.request()
val compressedRequest =
request.newBuilder()
//添加头部
.addHeader(
"User-Agent",
"Android"
)
.build()
chain.proceed(compressedRequest)
}
sHttpClient = builder
.callTimeout(40, TimeUnit.SECONDS)
.connectTimeout(40, TimeUnit.SECONDS)
.readTimeout(40, TimeUnit.SECONDS)
.writeTimeout(40, TimeUnit.SECONDS)
.build()
}
}
}
return sHttpClient
}
/**
* 获取接口服务
*/
fun getApi(): Api? {
if (sApi == null) {
synchronized(HttpHelper::class.java) {
if (sApi == null) {
val retrofit = createRetrofit(BASE_URL)
sApi = retrofit.create(Api::class.java)
}
}
}
return sApi
}
/**
* 获取Retrofit对象,定义返回类型的转换器
*/
private fun createRetrofit(baseUrl: String): Retrofit {
val gsonBuilder = GsonBuilder()
return Retrofit.Builder()
.client(getHttpClient())
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
.build()
}
}
}
(4)インターフェイスコールバッククラスSingleCallbackをカプセル化して、データを処理し、成功および失敗ステータスのデータを返します。
/**
* 接口请求基本回调
*/
abstract class SingleCallback<T : Result<*>?> :
Callback<T> {
//接口请求成功
override fun onResponse(
call: Call<T>,
response: Response<T>
) {
val result = response.body()
if (result == null) {
onFailure("-99", "请求异常", null)
} else {
if (apiFailure(result)) {
onFailure(result.errorCode, result.errorMsg ?: "", result)
} else {
onSuccess(result)
}
}
}
override fun onFailure(call: Call<T>, t: Throwable) {
Log.e("SingleCallback", "onFailure: " + t.message, t)
}
fun successCode(): String {
return "0"
}
fun apiFailure(result: T?): Boolean {
return result == null || successCode() != result.errorCode
}
/**
* 失败回调。默认已经将失败信息提示出来
*/
fun onFailure(code: String?, message: String, response: T?) {
Toast.makeText(App.getContext(), message, Toast.LENGTH_SHORT).show()
}
abstract fun onSuccess(response: T)
}
(5)リストインターフェースとサブアイテムのレイアウトを設計する
activity_main.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="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_article_data"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_user_data"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
item_article.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff">
<TextView
android:id="@+id/tv_article"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text=""
android:textSize="14dp" />
</LinearLayout>
item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff">
<TextView
android:id="@+id/tv_user"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text=""
android:textSize="14dp" />
</LinearLayout>
(6)エンティティカテゴリ
記事エンティティクラス
class Article {
var datas: List<ArticleData>? = null
}
ArticleDataエンティティクラス
class ArticleData{
val title: String? = null
}
ユーザーエンティティクラス
class User{
val name: String? = null
}
(7)ロジックおよびデータアダプタのコード記述
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val mUserList: MutableList<User> = ArrayList()
private var mArticleList: MutableList<ArticleData> = ArrayList();
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//或者这里可以不用findViewById,直接用布局中的id作为变量名也可以
var rvArticleData: RecyclerView = findViewById(R.id.rv_article_data)
var rvUserData: RecyclerView = findViewById(R.id.rv_user_data)
rvArticleData.layoutManager = LinearLayoutManager(this)
rvUserData.layoutManager = LinearLayoutManager(this)
rvArticleData.adapter = ArticleAdapter(this, mArticleList)
var userAdapter = UserAdapter(mUserList)
userAdapter.setOnUserClickListener(object : UserAdapter.OnUserClickListener {
override fun click(text: String?) {
Toast.makeText(applicationContext, text, Toast.LENGTH_SHORT).show()
}
})
rvUserData.adapter = userAdapter
//请求微信公众号接口
var api = HttpHelper.getApi()
api!!.getwxarticle()!!.enqueue(object : SingleCallback<Result<List<User>>>() {
override fun onSuccess(response: Result<List<User>>) {
if (response.data != null && (response.data?.size ?: 0 > 0)) {
mUserList.addAll(response.data!!)
rvUserData.adapter?.notifyDataSetChanged()
}
}
})
//请求文章接口
var api1 = HttpHelper.getApi()
api1!!.getArticle("1", "60")!!.enqueue(object : SingleCallback<Result<Article>>() {
override fun onSuccess(response: Result<Article>) {
if (response.data != null && response.data?.datas != null && response.data?.datas?.size ?: 0 > 0) {
mArticleList.addAll(response.data?.datas!!)
rvArticleData.adapter?.notifyDataSetChanged()
}
}
})
}
}
ArticleAdapter.kt
class ArticleAdapter(var mContext: Context, var mList: List<ArticleData>) :
RecyclerView.Adapter<ArticleAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var mTvArticle: TextView = view.tv_article
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_article,
parent,
false
)
)
}
override fun getItemCount(): Int {
return mList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.mTvArticle.text = mList[position].title
//设置点击事件,Lambda 表达式用着真的很舒服
holder.mTvArticle.setOnClickListener {
Toast.makeText(
mContext,
mList[position].title,
Toast.LENGTH_SHORT
).show()
}
}
UserAdapter.kt
class UserAdapter(var mList: List<User>) :
RecyclerView.Adapter<UserAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var mTvUser: TextView = view.tv_user
}
private var mUserClickListener: OnUserClickListener? = null
//设置点击事件回调,具体的实现在回调中定义
interface OnUserClickListener {
fun click(text: String?)
}
fun setOnUserClickListener(onUserClickListener: OnUserClickListener) {
this.mUserClickListener = onUserClickListener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_user,
parent,
false
)
)
}
override fun getItemCount(): Int {
return mList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.mTvUser.text = mList[position].name
holder.mTvUser.setOnClickListener {
mUserClickListener!!.click(mList[position].name)
}
}
これまでのところ、Kotlin + Retrofit + Recyclerviewの使用法をここで紹介します。関数のレンダリングを最初に示します。コードはコードクラウド、アドレスhttps://gitee.com/fjjxxy/kotlin_retrofitにアップロードされています。 git、疑問があります以下のQRコードをスキャンしてWeChatを追加してください。一緒に進歩します!最後になりましたが、皆様のご健康とご多幸をお祈り申し上げますとともに、ご支援、ご鞭撻を賜りますようお願い申し上げます。