【10】Kotlin项目实操之首页模块

(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~

【10】Kotlin项目实操之首页模块

1.OkHttp网络请求模式

(1)写代码应该先将接口写出来,按照接口标准来具体实现

1.1设计图

在这里插入图片描述

(1)使用OkHttp去访问服务器,最终一定会有一个成功与失败
(2)这个成功与失败,严格来讲就是一个Callback回调
(3)对这个Callback再次封装,便于控制成功与失败的操作。
(4)为什么这么设计?

  • 因为异步请求服务器,就会有成功与失败,没有封装之前,这个成功与失败的响应结果是异步的。
  • 而封装的目的一是为了将异步的成功与失败结果变成主线程,二是为了做数据过滤

1.2请求服务器API接口

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlinproject.data_model.local.request
 * @file
 * @Description:
 *
 * 1.请求服务器的一系列接口
 *
 * @date 2021-6-5 10:24
 * @since appVer
 */
interface IRequest {

    /**
     * 1.无参数
     * (1)NetWorkResultData:响应成功或失败的数据
     */
    fun instanceRequestAction(url:String,resultData: NetWorkResultData)

    /**
     * 1.有1个参数的
     */
    fun instanceRequestAction(url:String,value:String,resultData: NetWorkResultData)

    /**
     * 1.有2个参数的
     */
    fun instanceRequestAction(url:String,value1:String,value2:String,resultData: NetWorkResultData)

    /**
     * 1.有3个参数的
     */
    fun instanceRequestAction(url:String,value1:String,value2:String,value3:String,resultData: NetWorkResultData)

    /**
     * 用map做参数
     */
    fun instanceRequestAction(url:String,resultData: NetWorkResultData,parameter:Map<String,String>)
}

1.3服务器响应的封装

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlinproject.local.request
 * @file
 * @Description:
 * 1.对异步回调的封装
 * (1)使用OkHttp去访问服务器,最终一定会有一个成功与失败
 * (2)这个成功与失败,严格来讲就是一个Callback回调
 * (3)对这个Callback再次封装,便于控制成功与失败的操作。
 * (4)为什么这么设计?
 * - 因为异步请求服务器,就会有成功与失败,没有封装之前,这个成功与失败的响应结果是异步的。
 * - 而封装的目的一是为了将异步的成功与失败结果变成主线程,二是为了做数据过滤
 *
 * @date 2021-6-5 18:14
 * @since appVer
 */
abstract class NetWorkResultData : Callback {

    /**
     * 1.封装前的失败
     * 1.1使用Handler切换到主线程调用封装后的失败
     * 1.2确保在主线程执行
     */
    override fun onFailure(call: Call, e: IOException) {
        Log.e(Flag.TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>> onFailure: use okhttp network request TO Exception: ${e.message}" );

        Handler(Looper.getMainLooper(),object :Handler.Callback{
            override fun handleMessage(msg: Message): Boolean {

                //1.1.拿到信息message不为空的情况下执行let里面的内容 it==message本身
                e.message ?.let { requestError(it) }
                //1.2.为了保证系统继续执行,return false
                return false;
            }

        }).sendEmptyMessage(0)
    }

    /**
     * 1.封装前的成功
     * 1.1使用Handler切换到主线程调用封装后的成功,确保在主线程执行
     */
    override fun onResponse(call: Call, response: Response) {
        Handler(Looper.getMainLooper(),Handler.Callback {
            requestSuccess(response)
            false
        }).sendEmptyMessage(0)
    }

    /**
     * 1.封装后的失败
     */
    abstract fun requestError(info : String)

    /**
     * 1.封装后的成功
     * 拿到的是Okhttp的响应结果
     */
    abstract fun requestSuccess(result:Response)

}

1.4请求服务器API的具体实现

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlinproject.local.request
 * @file
 * @Description:
 * 1.请求服务器API的具体实现
 * (1).不使用派生单例,直接写object才是真正的单例
 * (2).派生与object实现单例时尽量使用object
 * (3).如果需要给单例传递参数,则使用派生更好
 * fun instanceRequestAPI(context:Context):IRequest = RequestAPI()
 * @date 2021-6-5 18:40
 * @since appVer
 */
object RequestAPI : IRequest{

    /**
     * 派生单例
     */
    /*companion object{
        fun instanceRequestAPI():IRequest = RequestAPI()
    }*/

    /**
     * 无参数
     */
    override fun instanceRequestAction(url: String, resultData: NetWorkResultData) {

    }

    /**
     * 1个参数
     */
    override fun instanceRequestAction(url: String, value: String, resultData: NetWorkResultData) {
        commonOKHttpRequestAction(url,resultData,value)
    }

    /**
     * 2个参数
     */
    override fun instanceRequestAction(
        url: String,
        value1: String,
        value2: String,
        resultData: NetWorkResultData
    ) {
        commonOKHttpRequestAction(url,resultData,value1,value2)
    }

    /**
     * 3个参数
     */
    override fun instanceRequestAction(
        url: String,
        value1: String,
        value2: String,
        value3: String,
        resultData: NetWorkResultData
    ) {
        commonOKHttpRequestAction(url,resultData,value1,value2,value3)
    }

    /**
     * Map多个参数
     */
    override fun instanceRequestAction(
        url: String,
        resultData: NetWorkResultData,
        parameter: Map<String, String>
    ) {

    }


    /** TODO ********************** 下面这一系列都是 OKHTTP 执行请求逻辑相关的 ************************/
    /**
     * 1.可变参数的情况
     * 1.1可变参数可以改为一个实体Bean类型的
     * 1.2此处是为了展示可变参数的形式,解决传递多个参数的问题
     */
    private fun commonOKHttpRequestAction(url:String , resultData : NetWorkResultData, vararg values:String){
        //1.创建一个OkHttpClient对象
        val okHttpclient = OkHttpClient()

        //2.构建参数的body MultipartBody.FORM表单形式
        val builder:MultipartBody.Builder = MultipartBody.Builder().setType(MultipartBody.FORM)

        //3.参数根据可变参数的数量变化而变化
        for(value in values){
            //3.1封装参数
            builder.addFormDataPart(Flag.PART,value)
        }

        //4.构建一个请求
        //4.1post提交里面是参数的builder
        //4.2url()请求路径
        val request:Request = Request.Builder()
            .url(url)
            .post(builder.build())
            .build()

        //5.发送一个请求给服务器
        okHttpclient.newCall(request).enqueue(resultData)
    }
}

2.用户请求流程图

2.1请求流程图

在这里插入图片描述

2.1请求响应实现

/**
 * @author XiongJie
 * @version appVer
 * @Package com.gdc.kotlinproject.modules.home
 * @file
 * @Description:
 * 1.首页的Fragment
 * (1)不使用MVP
 * @date 2021-6-4 18:09
 * @since appVer
 */
class HomeFragment:Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Toast.makeText(activity, "首页", Toast.LENGTH_SHORT).show()
        val root: View? = inflater.inflate(R.layout.fragment_home, container, false) //  null

        return root ?: super.onCreateView(inflater, container, savedInstanceState)
    }

    init {
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.personal_menu, menu)
    }


    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        requestHomeData()
    }

    /**
     * 1.请求服务器接口数据并解析
     */
    private fun requestHomeData(){
        RequestAPI.instanceRequestAction(Flag.SERVER_URL,"1",object :NetWorkResultData(){
            //1.1失败 主线程完成 已经在NetworkResultData切换为主线程执行
            override fun requestError(info: String) {
                Log.e(Flag.TAG, "requestHomeData requestError info:$info")
                showResultError(info)
            }

            //1.2成功 主线程完成 已经在NetworkResultData切换为主线程执行
            override fun requestSuccess(result: Response) {
                try {
                    val resultData = result.body()?.string().toString()

                    Log.e(Flag.TAG,
                        "成功  数据在response里面  获取后台给我们的JSON 字符串 resultData:$resultData")

                    //1.2.1Gson解析成可操作的对象
                    val gson = Gson()
                    val homeDataResponse: HomeDataResponse = gson.fromJson(resultData,HomeDataResponse::class.java)
                    showResultSuccess(homeDataResponse)
                } catch (e: Exception) {
                    e.printStackTrace()
                    Log.e(Flag.TAG, "requestSuccess 解析数据时Exception:${e.message}")
                }
            }

        })
    }

    /**
     * 首页的画面展示【成功】
     */
    private fun showResultSuccess(result: HomeDataResponse) {
        text_home.text = "欢迎同学们的到来>>>>>>>>>>>"

        home_listview.adapter = context?.myRun{
            HomeInfoListAdapter(it,result.data.news_list)
        }

        //两者图片的显示
        Glide.with(iv_top).load(result.data.company_list[0].image).into(iv_top)
        Glide.with(iv_bottom).load(result.data.ad_list[0].image).into(iv_bottom)
    }

    /**
     * 首页的画面展示【失败】
     */
    private fun showResultError(errorMsg: String) {
        Toast.makeText(activity, "首页数据请求失败: errorMsg:$errorMsg", Toast.LENGTH_SHORT).show()
    }
}

/**
 * 调用高阶函数
 */
fun <T, R> T.myRun(m: (T) -> R) : R  = m(this)

3.打赏鼓励

感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!

3.1微信打赏

在这里插入图片描述

3.2支付宝打赏

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值