Android Kotlin(二)—— Kotlin与Retrofit进行网络请求RecyclerView展示图片列表

接上一篇:Android Kotlin(一)—— Kotlin 入门与 HttpURLConnection 网络请求

一.获取插件和框架

1.摒弃findViewById 

apply plugin: 'kotlin-android-extensions'

2.Retrofit相关获取

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
compile 'com.google.code.gson:gson:2.8.0'

3.Glide 

mavenCentral()
maven { url 'https://maven.google.com' }

compile 'com.github.bumptech.glide:glide:4.2.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'

4.JsonToKotlinClass 插件:将json解析为kotlin 的 Bean类

获取方式:可直接在Studio中  File --> Settings --> Plugins --> Browse Repositories -->搜索 JsonToKotlinClass

使用方法:http://blog.csdn.net/wuseal/article/details/77508585

二.Retrofit

网络请求地址:http://route.showapi.com/197-1?showapi_appid=42684&showapi_sign=f6527e909abc4edea350ec8b9a9db0f5&num=10

数据来源网址:易源数据  https://www.showapi.com/

1.获取JSON 转换为Bean类

JSON数据:

{
    "showapi_res_code": 0,
    "showapi_res_error": "",
    "showapi_res_body": {
        "newslist": [{
            "title": "甜美女神 sugar小甜心CC 酥胸美臀大尺度比基尼巴厘岛写真",
            "picUrl": "http://m.xxxiao.com/wp-content/uploads/sites/3/2016/09/m.xxxiao.com_7f98c6da4ae2eaf1536b1d7d69e05157-682x1024.jpg",
            "description": "美女写真",
            "ctime": "2016-09-27 20:00",
            "url": "http://m.xxxiao.com/75780"
        }],
        "code": 200,
        "msg": "success"
    }
}

JsonToKotlinClass 插件转Bean类

data class ImageBean(
        @SerializedName("showapi_res_code") var showapiResCode: Int, 
        @SerializedName("showapi_res_error") var showapiResError: String,
        @SerializedName("showapi_res_body") var showapiResBody: ShowapiResBody
)

data class ShowapiResBody(
        @SerializedName("newslist") var newslist: List<Newslist>,
        @SerializedName("code") var code: Int, 
        @SerializedName("msg") var msg: String 
)

data class Newslist(
        @SerializedName("title") var title: String, 
        @SerializedName("picUrl") var picUrl: String, 
        @SerializedName("description") var description: String, 
        @SerializedName("ctime") var ctime: String, 
        @SerializedName("url") var url: String 
)

2.Post方式网络请求

API接口

interface PictureApi {
    @POST("197-1")
    @FormUrlEncoded
    fun getPicture(@Field("showapi_appid") showapi_appid: String, 
                   @Field("showapi_sign") showapi_sign: String, 
                   @Field("num") num: Int) : Call<ImageBean>
}

网络请求

class HttpManager {
    var retrofit = Retrofit.Builder()
            .baseUrl("http://route.showapi.com/")   //基地址
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    fun getPicture(num: Int, success: (ImageBean) -> Unit, fail: (String) -> Unit) {
        var pictureApi: PictureApi = retrofit.create(PictureApi::class.java)
        var call: Call<ImageBean> = pictureApi.getPicture("42684", "f6527e909abc4edea350ec8b9a9db0f5", num)
        call.enqueue(object : Callback<ImageBean> {
            override fun onResponse(call: Call<ImageBean>?, response: Response<ImageBean>) {
                success(response.body()!!)
            }
            override fun onFailure(call: Call<ImageBean>?, t: Throwable?) {
                fail(t.toString())
            }
        })
    }
}

在此处

success: (ImageBean) -> Unit  与 fail: (String) -> Unit 为回掉接口

在Kotlin中可以不用 再像Java中还需要重新创建接口,可以直接编写

success: (ImageBean) -> Unit 对应Java中的  void success(ImageBean imagebean)

fail: (String) -> Unit 对应Java中的 void fail(String str)

PictureApi::class.java 在Kotlin中 还需要Java类时 使用 ::.class.java 这种方式

三.RecyclerView 与 Adapter

class PictureAdapter(private var list: List<Newslist>) : RecyclerView.Adapter<PictureAdapter.MyViewHolder>() {
    
    fun notifyDataChange(list: List<Newslist>) {       //更新适配器数据
        this.list = list
        notifyDataSetChanged()
    }

    override fun getItemCount(): Int {
        return list.size
    }

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

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.textView.text = list[position].title //展示图片标题
         Glide.with(holder.imageView)                //ImageView中展示图片
                .load(list[position].picUrl)
               .into(holder.imageView)
    }

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var textView = itemView.findViewById(R.id.TextView) as TextView
        var imageView = itemView.findViewById(R.id.ImageView) as ImageView
    }
}

上面ViewHolder 是在sdk 25的情况下 findViewById 在 SDK 26中 改为了以下模式

@Nullable
public final <T extends View> T findViewById(@IdRes int id) {
    if (id == NO_ID) {
        return null;
    }
    return findViewTraversal(id);
}

对应写法

var textView = itemView.findViewById<TextView>(R.id.TextView)
var imageView = itemView.findViewById<ImageView>(R.id.ImageView)

或者

var textView: TextView = itemView.findViewById(R.id.TextView)
var imageView: ImageView = itemView.findViewById(R.id.ImageView)

四.Activity中使用

class TestActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)

        var adapter = PictureAdapter(ArrayList()) //适配器,默认一个空的集合,等网络请求后更新数据
         recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter

        button.setOnClickListener {
            //按钮点击事件
            HttpManager().getPicture(
                    10, //网络请求 5条数据 num表示网络请求返回的数据数量
                    { adapter.notifyDataChange(it.showapiResBody.newslist) }, //成功的回掉接口
                    { Toast.makeText(this, it, Toast.LENGTH_SHORT).show() } //失败的回掉接口
            )
        }
    }
}

五.加上RecyclerView Item点击事件

在adapter中 

var mListener: ((pos: Int) -> Unit)? = null
fun setOnItemClickListener(listener: ((pos: Int) -> Unit)) {
    mListener = listener
}

holder.imageView.setOnClickListener {
    mListener?.invoke(position)
}

在Activity中  点击某个Item 得到点击的位置 并吐司

adapter.setOnItemClickListener {
    Toast.makeText(this, it.toString(), Toast.LENGTH_SHORT).show()
}

附上XML  

activity中

<?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="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击我吧" />

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

RecyclerView Item中

<?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:orientation="vertical">

    <TextView
        android:id="@+id/TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/ImageView"
        android:layout_width="wrap_content"
        android:layout_height="180dp" />
</LinearLayout>

别忘记网络请求权限

<uses-permission android:name="android.permission.INTERNET" />



猜你喜欢

转载自blog.csdn.net/ww897532167/article/details/78338789