引入:话不多说,网上思想原理多的是,我这里只研究实战,施主,且看:
目的:使用Kotlin搭建MVP,采用Retrofit结合RXJava网络框架点击按钮创建线程请求接口,把线程添加到线程池,请求完成。
**一、**在项目中配置RXJava:
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"
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'com.recker.flybanner:flybanner:1.3'
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()
}
//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)
}
companion object {
val instance: RetrofitUtils
get() = RetroHolder.retro
}
}
**四、**写一个契约类:
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>)
}
}
**五、**写一个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!!.onRequestOk(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)
}
}
}
**九、**Glide图片工具类:
class GlideUtil {
//默认加载
fun loadImageView(mContext: Context, path: String, mImageView: ImageView) {
Glide.with(mContext).load(path).into(mImageView)
}
//圆角加载
fun CircularImageView(mContext: Context, path: Any, mImageView: ImageView) {
//设置图片圆角角度
val roundedCorners = RoundedCorners(10)
//通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
val options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300)
Glide.with(mContext).load(path).apply(options).into(mImageView)
}
//圆形加载
fun RoundImageView(mContext: Context, path: String, mImageView: ImageView) {
//设置图片圆角角度
val roundedCorners = RoundedCorners(200)
//通过RequestOptions扩展功]能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
val options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300)
Glide.with(mContext).load(path).apply(options).into(mImageView)
}
}
**十、**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="
}
十二:主页面:
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 mdata : MutableList<String>
lateinit var myAllHostAdapter : MyAdapter
private val presenter: PresenterImpl? = PresenterImpl(this)
var threadPoolExecutor : ThreadPoolExecutor = ThreadPoolExecutor(3, 5, 1, TimeUnit.SECONDS, LinkedBlockingQueue<Runnable>(100))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mList= mutableListOf()
val manager1 = LinearLayoutManager(this)
recy.setLayoutManager(manager1)
myAllHostAdapter = MyAdapter(mList, this)
recy.setAdapter(myAllHostAdapter)
send_data.setOnClickListener {
/*var ins : Intent = Intent(this,Main2Activity::class.java)
startActivity(ins)*/
var runn : Runnable = Runnable (){
run {
presenter!!.startRequest(Contacts.Bas,head,map,MyData::class.java)
}
}
threadPoolExecutor.execute(runn)
}
}
override fun onRequestOk(data: Any) {
if(data is MyData) {
var myHostMovie = data as MyData
mList.addAll(myHostMovie!!.data)
myAllHostAdapter!!.notifyDataSetChanged()
mdata = mutableListOf()
for ( item in mList){
mdata.add(item.thumbnailPicS02)
}
fly.setImagesUrl(mdata);
}
}
override fun onRequestNo(error: String) {
Log.d("zzz",error+"小区")
}
}
**十三、**布局:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请求数据"
android:gravity="center"
android:id="@+id/send_data"
android:layout_gravity="center"/>
<com.recker.flybanner.FlyBanner
android:layout_width="match_parent"
android:layout_height="150dp"
android:id="@+id/fly"></com.recker.flybanner.FlyBanner>
<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>
在写Bean类的时候,要导入JSON TO Kotlin Class 这个插件,快捷键是alt+k,施主,请看:
JsonText是放字符串的点击Generate生成bean类,不过第一次要设置格式点击settings,出现此图:
在点击:
选上Gson,点击OK