引入:话不多说,网上思想原理多的是,我这里只研究实战,施主,且看:
在这里插入图片描述目的:使用Kotlin搭建MVP,采用Retrofit结合RXJava网络框架点击按钮创建线程请求接口。
一、在项目中配置RXJava:(在项目build文件的最外面添加)
ext {
// Sdk and tools
minSdkVersion = 19
targetSdkVersion = 26
compileSdkVersion = 26
buildToolsVersion = '26.0.2'
//support版本
supportVersion = '27.1.0'
constraintLayout = '1.0.2'
junit = '4.12'
testRunner = '1.0.1'
espressoCore = '3.0.1'
interceptor = "3.11.0"
retrofit = '2.3.0'
converterGson = '2.3.0'
rxandroid = '1.2.1'
rxjava = '1.3.0'
rxbus = '1.0.6'
adapterRxjava = '2.0.2'
}
二、在自己model中加入依赖:
implementation "com.squareup.retrofit2:retrofit:$rootProject.retrofit"
implementation "com.squareup.retrofit2:converter-gson:$rootProject.converterGson"
implementation "io.reactivex:rxandroid:$rootProject.rxandroid"
implementation "io.reactivex:rxjava:$rootProject.rxjava"
implementation "com.hwangjr.rxbus:rxbus:$rootProject.rxbus"
implementation "com.squareup.retrofit2:adapter-rxjava:$rootProject.adapterRxjava"
implementation 'com.android.support:recyclerview-v7:28.0.0'
//日志拦截器
implementation "com.squareup.okhttp3:logging-interceptor:$rootProject.interceptor"
//glide图片加载
implementation 'com.github.bumptech.glide:glide:4.9.0'
三、添加权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
四、开始代码
接口
interface MyInterface {
interface MyCallBack<T> {
fun onSuccess(data: T)
fun onError(error: String)
}
interface Model {
fun<T> getData(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>, kind: Class<T>, myCallBack: MyCallBack<Any>)
}
interface MyView<T> {
fun onRequestOk(data: T)
fun onRequestNo(error: String)
}
interface Presenter {
fun<T> startRequest(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>, kind: Class<T>)
}
}
写Retrofit和RXJava请求的网络工具类
class RetrofitUtils private constructor() {
private val myApiService: MyApiService
init {
//日志拦截器
val loggingInterceptor = HttpLoggingInterceptor()
//设置日志拦截器的等级
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
val okHttpClient = OkHttpClient.Builder()
.readTimeout(20, TimeUnit.SECONDS)
.connectTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor)
//当网络请求失败的时候,等到网络正常自动加载
.retryOnConnectionFailure(true).build()
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(Contacts.BASE_URL)
.client(okHttpClient)
.build()
myApiService = retrofit.create(MyApiService::class.java)
}
//这两段是实现单例
private object RetroHolder {
val retro = RetrofitUtils()
}
companion object {
val instance: RetrofitUtils
get() = RetroHolder.retro
}
//get请求
operator fun get(url: String, head: HashMap<String, Any>?, map: HashMap<String, Any>?, httpListtener: HttpListtener?) {
var head = head
var map = map
if (head == null) {
head = HashMap()
}
if (map == null) {
map = HashMap()
}
val observer = object : Observer<ResponseBody> {
override fun onCompleted() {
}
override fun onError(e: Throwable) {
if (httpListtener != null) {
Log.e("zzz", "onError: " + e.message)
httpListtener.OnError(e.message!!)
}
}
override fun onNext(responseBody: ResponseBody) {
if (httpListtener != null) {
try {
httpListtener.OnSuccess(responseBody.string())
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
//请求网络放在子线程
myApiService[url, head, map].subscribeOn(Schedulers.io())
//成功后回调到主线程(observeOn)是观察者
.observeOn(AndroidSchedulers.mainThread())
//订阅
.subscribe(observer)
}
//post请求
fun post(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>?, httpListtener: HttpListtener?) {
var map = map
val observer = object : Observer<ResponseBody> {
override fun onCompleted() {
}
override fun onError(e: Throwable) {
httpListtener?.OnError(e.message!!)
}
override fun onNext(responseBody: ResponseBody) {
if (httpListtener != null) {
try {
httpListtener.OnSuccess(responseBody.string())
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
if (map == null) {
map = HashMap()
}
myApiService.post(url, head, map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer)
}
//put请求
fun put(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>?, httpListtener: HttpListtener?) {
var map = map
val observer = object : Observer<ResponseBody> {
override fun onCompleted() {
}
override fun onError(e: Throwable) {
httpListtener?.OnError(e.message!!)
}
override fun onNext(responseBody: ResponseBody) {
if (httpListtener != null) {
try {
httpListtener.OnSuccess(responseBody.string())
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
if (map == null) {
map = HashMap()
}
myApiService.put(url, head, map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer)
}
//post请求
fun delete(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>?, httpListtener: HttpListtener?) {
var map = map
val observer = object : Observer<ResponseBody> {
override fun onCompleted() {
}
override fun onError(e: Throwable) {
httpListtener?.OnError(e.message!!)
}
override fun onNext(responseBody: ResponseBody) {
if (httpListtener != null) {
try {
httpListtener.OnSuccess(responseBody.string())
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
if (map == null) {
map = HashMap()
}
myApiService.delete(url, head, map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer)
}
//图片请求
fun postHeader(url: String, header: HashMap<String, Any>?, path: String, okHttpFace: HttpListtener?) {
var header = header
if (header == null) {
header = HashMap()
}
val observer = object : Observer<ResponseBody> {
override fun onCompleted() {
}
override fun onError(e: Throwable) {
okHttpFace?.OnError(e.message!!)
}
override fun onNext(responseBody: ResponseBody) {
if (okHttpFace != null) {
try {
okHttpFace.OnSuccess(responseBody.string())
} catch (e: IOException) {
e.printStackTrace()
}
}
}
}
val file = File(path)
val requestBody = RequestBody.create(MediaType.parse("multipart/octet-stream"), file)
val builder = MultipartBody.Builder()
builder.setType(MultipartBody.FORM)
builder.addFormDataPart("image", file.name, requestBody)
myApiService.postHeader(url, header, builder.build())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer)
}
//自定义接口
interface HttpListtener {
fun OnSuccess(jsonStr: String)
fun OnError(error: String)
}
}
一个model的实现类
class ModelImpl : MyInterface.Model {
override fun<T> getData(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>, kind: Class<T>, myCallBack: MyInterface.MyCallBack<Any>) {
val gson = Gson()
RetrofitUtils.instance.get(url,head,map, httpListtener = object : RetrofitUtils.HttpListtener{
override fun OnSuccess(jsonStr: String) {
var o = gson.fromJson(jsonStr, kind)
myCallBack.onSuccess(o!!)
}
override fun OnError(error: String) {
myCallBack.onSuccess(error!!)
}
})
}
}
一个Presenter的实现类
class PresenterImpl : MyInterface.Presenter {
private var myView: MyInterface.MyView<Any>?=null
private var model: ModelImpl? = null
constructor(myView: MyInterface.MyView<Any>) {
this.myView = myView
model = ModelImpl()
}
override fun<T> startRequest(url: String, head: HashMap<String, Any>, map: HashMap<String, Any>, kind: Class<T>) {
model!!.getData(url,head,map,kind,object : MyInterface.MyCallBack<Any>{
override fun onSuccess(data: Any) {
myView!!.onRequestOk(data);
}
override fun onError(error: String) {
myView!!.onRequestNo(error);
}
})
}
}
Bean类
data class MyData(
@SerializedName("code")
val code: Int,
@SerializedName("data")
val `data`: List<Data>,
@SerializedName("msg")
val msg: String
)
data class Data(
@SerializedName("author_name")
val authorName: String,
@SerializedName("category")
val category: String,
@SerializedName("date")
val date: String,
@SerializedName("thumbnail_pic_s")
val thumbnailPicS: String,
@SerializedName("thumbnail_pic_s02")
val thumbnailPicS02: String,
@SerializedName("thumbnail_pic_s03")
val thumbnailPicS03: String,
@SerializedName("title")
val title: String,
@SerializedName("uniquekey")
val uniquekey: String,
@SerializedName("url")
val url: String
)
适配器工具类
class MyAdapter(mList: List<Data>, mainActivity: MainActivity) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
private var mList: List<Data>? = mList
private var mContext: Context? = mainActivity
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): MyAdapter.ViewHolder {
val view = View.inflate(mContext, R.layout.activity_item, null)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return mList!!.size
}
override fun onBindViewHolder(p0: MyAdapter.ViewHolder, p1: Int) {
Glide.with(mContext!!).load(mList!!.get(p1).thumbnailPicS).into(p0.simpleDraweeView)
p0.simp_cinema_tv.text=mList!!.get(p1).title
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var simpleDraweeView: ImageView
var simp_cinema_tv : TextView
init {
simpleDraweeView = itemView.findViewById(R.id.simp_cinema_flow)
simp_cinema_tv = itemView.findViewById(R.id.simp_cinema_tv)
}
}
}
Api
interface MyApiService {
@GET
operator fun get(@Url murl: String, @HeaderMap headermap: HashMap<String, Any>, @QueryMap map: HashMap<String, Any>): Observable<ResponseBody>
@FormUrlEncoded
@POST
fun post(@Url murl: String, @HeaderMap headermap: HashMap<String, Any>, @FieldMap map: HashMap<String, Any>): Observable<ResponseBody>
@POST
fun postHeader(@Url url: String, @HeaderMap header: HashMap<String, Any>, @Body body: MultipartBody): Observable<ResponseBody>
@PUT
fun put(@Url url: String, @HeaderMap headermap: Map<String, Any>, @FieldMap map: Map<String, Any>): Observable<ResponseBody>
@DELETE
fun delete(@Url url: String, @HeaderMap headermap: Map<String, Any>, @FieldMap map: Map<String, Any>): Observable<ResponseBody>
}
接口
object Contacts {
var BASE_URL = "http://www.xieast.com/api/"
var Bas = "news/news.php?page="
}
Activity页面
class MainActivity :AppCompatActivity(), MyInterface.MyView<Any> {
private val head : HashMap<String,Any> = HashMap()
private val map : HashMap<String,Any> = HashMap()
lateinit var mList: MutableList<Data>
lateinit var myAllHostAdapter : MyAdapter
private val presenter: PresenterImpl? = PresenterImpl(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mList= mutableListOf()
val manager1 = LinearLayoutManager(this)
send_recy.layoutManager = Manager1
myAllHostAdapter = MyAdapter(mList, this)
recy.setAdapter(myAllHostAdapter)
}
override fun onRequestOk(data: Any) {
if(data is MyData) {
var myHostMovie = data as MyData
mList.addAll(myHostMovie!!.data)
myAllHostAdapter!!.notifyDataSetChanged()
}
}
override fun onRequestNo(error: String) {
Log.d("zzz",error+"小区")
}
}
Activity的布局
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recy"></android.support.v7.widget.RecyclerView>
</LinearLayout>
适配器中item的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/simp_cinema_flow"
android:layout_width="150dp"
android:layout_height="150dp" />
<TextView
android:id="@+id/simp_cinema_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout>
在写Bean类的时候,要导入JSON TO Kotlin Class 这个插件,快捷键是alt+k,施主,请看:
JsonText是放字符串的点击Generate生成bean类,不过第一次要设置格式点击settings,出现此图: