Retrofit框架的简单使用(上)

一,导入依赖

implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
在AndroidManifest.xml中记得申请网络权限
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

二,定义个请求接口

import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface ApiService {

    companion object {
        const val BASE_URL = "https://api.sunofbeaches.com/shop/"
    }

    //最后组合成完整地址:https://api.sunofbeaches.com/shop/discovery/categories
    @GET("discovery/categories")
    //@Query注解是查询参数,如果多个参数就写多个注解,用逗号分开
    fun test(@Query("test") str: String): Call<String>

}

三,开始使用

    var TAG: String = "Xiang"

    /**
     * 创建拦截器
     */
    var intercept = HttpLoggingInterceptor {
        Log.e(TAG, "onHttpRetrofit: $it")
    }.setLevel(HttpLoggingInterceptor.Level.BODY)

    /**
     * 添加拦截器
     */
    var okHttpClient = OkHttpClient.Builder().addInterceptor(intercept).build()


    var retrofit = Retrofit.Builder()
        .baseUrl(ApiService.BASE_URL)
        .addConverterFactory(ScalarsConverterFactory.create())
        .client(okHttpClient)
        .build()

    /**
     * 获取动态代理实例
     */
    var apiService = retrofit.create(ApiService::class.java)


    /**
     * 异步请求,不用协程或者子线程。
     */
//    apiService.test("100").enqueue(object : retrofit2.Callback<String> {
//        override fun onResponse(
//            call: retrofit2.Call<String>,
//            response: retrofit2.Response<String>
//        ) {
//            /**
//             * 请求成功
//             */
//            if (response.isSuccessful) {
//                Log.e(TAG, "onResponse: ${response.body()}")
//            }
//        }
//
//        override fun onFailure(call: retrofit2.Call<String>, t: Throwable) {
//            //请求是吧
//            Log.e(TAG, "onFailure: ${t.message}")
//        }
//
//    })

    /**
     * 同步请求,必须用协程或者线程去执行,不然会阻塞UI(主)线程
     */
    GlobalScope.async {
        var response = apiService.test("100").execute();
        if (response.isSuccessful) {
            Log.e(TAG, "onResponse: ${response.body()}")
        } else {
            Log.e(TAG, "onFailure: ${response.message()}")
        }
    }

关于Post请求,请跳转 Retrofit框架的简单使用(下)

HttpOk3通过Kotlin 请求简单Demo

开启网络权限

需要在AndroidManifest.xml 的manifest下添加网络权限

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

第一步:引入依赖

 implementation("com.squareup.okhttp3:okhttp:4.9.0")
 implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")

添加过滤器

import android.util.Log
import okhttp3.Interceptor
import okhttp3.Response

class LogIntercept : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        var url = request.url
        Log.e("Xiang", "intercept: 这里是请求过滤器,请求地址:${url}")
        return chain.proceed(request)
    }
}

二:GET请求

        GlobalScope.async {
            var okHttpClient = OkHttpClient.Builder().addInterceptor(LogIntercept()).build()
            var request: Request = Request.Builder()
                .url("https://api.admin.com/shop/discovery/categories")
                .build()
            okHttpClient.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {

                }
                override fun onResponse(call: Call, response: Response) {
                    if (response.isSuccessful) {
                        response.body?.let {
                            val dataBody = it.string()
                            Log.e("Xiang", dataBody)
                        }
                    }
                }
            })
        }

三:form表单提交

 var okHttpClient = OkHttpClient.Builder().addInterceptor(LogIntercept()).build()
    var formBody = FormBody.Builder()
        .add("AD_user","admin")
        .add("AD_pass","888888")
        .build()

    var request: Request = Request.Builder()
        .url("https://api.admin.com/admin/Chk_login.asp")
        .post(formBody)
        .build()

    okHttpClient.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            e.message?.let {
                Log.e("Xiang", it.toString())
            }
        }
        override fun onResponse(call: Call, response: Response) {
            if (response.isSuccessful) {
                response.body?.let {
                    val dataBody = it.string()
                    Log.e("Xiang", dataBody)
                }
            }
        }
    })

四:JSON格式提交

    var okHttpClient = OkHttpClient.Builder().addInterceptor(LogIntercept()).build()
    var stringBody = "{\"username\":\"123456\",\"password\":\"123456789\"}"
        .toRequestBody("application/json;charset=utf-8".toMediaType())
    var request: Request = Request.Builder()
        .url("https://auth.admin.com/login")
        .post(stringBody)
        .build()

LiveData和ViewModel联合使用,简单入门

我们得首先明白ViewModel只是一个记录业务逻辑和屏幕状态的容器,LiveData是一个可以被观察数据集合

第一步,创建容器

我们新建一个ViewModel容器类。比如MyViewModel

class MyViewModel : ViewModel() {}  

第二步,在容器中创建LiveData可被观察的数据,比如一个String类型的数据。

class MyViewModel : ViewModel() {

    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }
}

第三步,在界面组件(Activity或Fragment)中去使用。

首先添加一个观察者,这样就可以实时的去关键currentName的变动。

//我们先在Activity中添加ViewModel 
private val model: MyViewModel by viewModels()

//在组件中使用。
@Composable
fun GetMessage(model: MyViewModel, cotnent: ComponentActivity) {
    var message by remember {
        mutableStateOf("")
    }
//建立一个观察者
    var observer = Observer<String> {
        message = it
    }

//添加观察者,cotnent:Activity对象,observer观察者对象
model.currentName.observe(cotnent, observer)

    Text(text = "内容:$message")
}

第四步,设置改变LiveData数据

 model.currentName.setValue("这是更新的内容")

Lifecycle简单使用方法。

Lifecycle的组件作用就是解耦Activity的生命周期,没当Activity的生命周期改变之后通知Lifecycle观察者。

第一,导入Lifecycle依赖

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")

第二,建立一个观察者,实现DefaultLifecycleObserver接口

重写DefaultLifecycleObserver的生命周期函数,比如我们要观察Activity的onStart、onStop周期函数,那么就重写这两个函数。

import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner

class TestModel(var names:String):DefaultLifecycleObserver {

    lateinit var name:String

    init{
        this.name = names
    }

    override fun onStart(owner: LifecycleOwner) {
        Log.e("Xiang","执行了start $name")
    }

    override fun onStop(owner: LifecycleOwner) {
        Log.e("Xiang","执行了stop $name")
    }


}

第三,绑定到Activity去。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //添加观察者
        lifecycle.addObserver(TestModel("kt"))
        setContent {
            Text(text = "hi Android")
        }
    }
}
  • 当MainActivity 这个Activity的生命周期发生变化之后,我们可以在观察者TestModel中同步对应的方法。

Android开发在layout添加子目录方法(Kotlin版本)

如果把所有的布局文件和fragment文件都放在layout这一个目录下面,随着文件增多,越发越乱,那么我们在layout下再见几个文件对布局文件进行分组分类。

第一步 显示Android目录为Project状态,在 build.gradle.kts 文件中添加一下代码

android {    
.......
    sourceSets {
        getByName("main") {
            res {
                srcDirs(
                    "src/main/res/layout/activity",
                    "src/main/res/layout/fragment",
                    "src/main/res"
                )
            }
        }
    }
}

那么对应的文件布局分为active和fragment,对应的文件目录格式如下

--res/layout
----res/layout/activity/layout
----res/layout/fragment/layout

xml布局文件可以放在res/layout、res/layout/activity/layout、res/layout/fragment/layout目录下,如果自己有其他文件分类,可以自行添加。