tags: Kotlin
Previous Blog We told Kotlin + Retrofit + RXJAVA to implement a simple implementation of network requests. This blog will implement the Simple Package of Kotlin + Retrofit + RxJava + MVP to implement network requests.
The requested URL is: const val base_server_url = "https://www.wanandroid.com"
1. TheBaseActivity code is as follows:

/**
* @ Author: njb
* @ : 2020/12/3 17:33
* @ Description:
*/
abstract class BaseActivity<P : BasePresenter<*>> : AppCompatActivity(), BaseView {
lateinit var context: Context
protected var presenter: P? = null
protected var unbinder: Unbinder? = null
private var waitDialog: LoadingDialog? = null
protected abstract val layoutId: Int
protected abstract fun createPresenter(): P
protected abstract fun initView()
protected abstract fun addListener()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (layoutId != 0) {
setContentView(layoutId)
}
unbinder = ButterKnife.bind(this)
context = this
presenter = createPresenter()
initView()
addListener()
}
/**
* Open Activity
*
* @param cls
*/
fun startA(cls: Class<*>) {
val intent = Intent(context, cls)
startActivity(intent)
}
public override fun onPause() {
super.onPause()
}
override fun onDestroy() {
super.onDestroy()
presenter!!.detachView()
unbinder!!.unbind()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
onBackPressed()
}
}
return super.onOptionsItemSelected(item)
}
override fun onBackPressed() {
super.onBackPressed()
// Fragment outlet
val count = supportFragmentManager.backStackEntryCount
if (count == 0) {
super.onBackPressed()
} else {
supportFragmentManager.popBackStack()
}
}
/**
* @param s
*/
fun showtoast(s: String) {
Toast.makeText(context, s, Toast.LENGTH_SHORT).show()
}
fun showFileDialog() {}
fun hideFileDialog() {}
/**
* Display loading box
*
* @param textRes
* @param color
*/
fun showWaitDialog(textRes: String, color: Int) {
if (null == waitDialog) {
waitDialog = LoadingDialog(this, textRes, color)
} else {
waitDialog!!.setShowText(textRes)
if (!waitDialog!!.isShown) {
waitDialog!!.showUp()
}
}
}
/**
* Display loading box
*/
fun showWaitDialog() {
if (null == waitDialog) {
waitDialog = LoadingDialog(this)
} else {
waitDialog!!.setShowText("")
if (!waitDialog!!.isShown) {
waitDialog!!.showUp()
}
}
}
/**
* Show ProgressBar
*
* @Param Textres Needs the word to be prompted
*/
fun showWaitDialog(textRes: Int) {
if (null == waitDialog) {
waitDialog = LoadingDialog(this, textRes)
} else {
waitDialog!!.setShowText(textRes)
if (!waitDialog!!.isShown) {
waitDialog!!.showUp()
}
}
}
/**
* Destroy ProgressBar
*/
fun dismissWaitDialog() {
if (null != waitDialog && waitDialog!!.isShown) {
waitDialog!!.dismiss()
}
}
/**
* Get View by resource RES
*
* @param res
* @return
*/
fun getViewByRes(@LayoutRes res: Int): View {
return LayoutInflater.from(context).inflate(res, null)
}
/**
* Get text for textView
*
* @param tv
* @return
*/
fun getTV(tv: TextView?): String {
return tv?.text?.toString()?.trim { it <= ' ' } ?: ""
}
override fun showError(msg: String) {
showtoast(msg)
}
override fun onErrorCode(model: BaseResult<Any>) {
when {
model.errorCode < 0.toString() -> showtoast(model.errorMsg)
}
}
override fun showLoadingFileDialog() {
showWaitDialog()
}
override fun hideLoadingFileDialog() {
dismissWaitDialog()
}
override fun onProgress(totalSize: Long, downSize: Long) {}
fun addFragmentToActivity(
fragmentManager: FragmentManager,
fragment: Fragment, frameId: Int
) {
val transaction = fragmentManager.beginTransaction()
if (!fragment.isAdded)
transaction.add(frameId, fragment)
fragmentManager.fragments.filter { it.id == fragment.id }.map { transaction.hide(it) }
transaction.show(fragment)
transaction.commit()
}
2. Basepresenter code is as follows:

public class BasePresenter<V extends BaseView> {
private CompositeDisposable compositeDisposable;
public V baseView;
protected ApiServer apiServer = ApiRetrofit.getInstance().getApiService();
public BasePresenter(V baseView) {
this.baseView = baseView;
}
/**
* Release binding
*/
public void detachView() {
baseView = null;
removeDisposable();
}
/**
* Return to View
*
* @return
*/
public V getBaseView() {
return baseView;
}
public void addDisposable(Observable<?> observable, DisposableObserver observer) {
if (compositeDisposable == null) {
compositeDisposable = new CompositeDisposable();
}
compositeDisposable.add(
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(observer));
}
public void removeDisposable() {
if (compositeDisposable != null) {
compositeDisposable.dispose();
}
}
}
3. The Basefragment code is as follows:

/**
* @ Author: njb
* @ : 2020/12/3 17:38
* @ Description:
*/
abstract class BaseFragment<P : BasePresenter<*>> : Fragment(), BaseView {
internal var context: Context? = null
private var dialog: ProgressDialog? = null
// Control is initialized
private var isViewCreated: Boolean = false
// Whether the current Fragment is loaded, if loading data is loaded, no more
private var isLoadCompleted: Boolean = false
/ / Is not visible
private var isUIVisible: Boolean = false
protected var presenter: P? = null
/**
* Load layout
*/
@LayoutRes
abstract fun getLayoutId(): Int
// Lazy loading, mandatory subtyver rewriting
abstract fun loadData()
abstract fun initView()
abstract fun addListener()
abstract fun createPresenter(): P
abstract fun setTitle()
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
isUIVisible = isVisibleToUser
if (isVisibleToUser && isViewCreated && isUIVisible && !isLoadCompleted) {
isLoadCompleted = true
loadData()
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (isViewCreated && isUIVisible) {
loadData()
isLoadCompleted = true
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val rootView = inflater.inflate(getLayoutId(), container, false)
/* presenter = createPresenter()
isViewCreated = true
initView()
addListener()*/
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter = createPresenter()
isViewCreated = true
initView()
addListener()
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
isUIVisible = !hidden
isLoadCompleted = !hidden
}
override fun onAttach(context: Context) {
super.onAttach(context)
this.context = context
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onDestroyView() {
super.onDestroyView()
if (presenter != null) {
presenter!!.detachView()
}
}
/**
* Open the specified Activity
*
* @param cls
*/
fun startA(cls: Class<*>) {
val intent = Intent(context, cls)
startActivity(intent)
}
fun setStatusBar(view: View?) {
if (view == null) {
return
}
}
/**
* toast
*
* @param msg
*/
fun showtoast(msg: String) {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
}
/**
* Show loading animation
*/
fun showLoadingDialog() {
if (dialog != null && dialog!!.isShowing) {
return
}
if (null == dialog) {
dialog = ProgressDialog(context, R.style.AlertDialogStyle)
}
dialog!!.setCancelable(false)
dialog!!.show()
}
/**
* Hidden loading animation
*/
fun closeLoadingDialog() {
if (dialog != null && dialog!!.isShowing) {
dialog!!.dismiss()
}
}
/**
* Get View by resource RES
*
* @param res
* @return
*/
fun getViewByRes(@LayoutRes res: Int): View {
return LayoutInflater.from(context).inflate(res, null)
}
/**
* Get text for textView
*
* @param tv
* @return
*/
fun getTV(tv: TextView?): String {
return tv?.text?.toString()?.trim { it <= ' ' } ?: ""
}
private fun showFileDialog() {}
private fun hideFileDialog() {}
override fun hideLoading() {
closeLoadingDialog()
}
override fun showError(msg: String) {
showtoast(msg)
}
override fun onErrorCode(model: BaseResult<Any>) {
when {
model.errorCode < 0.toString() -> showtoast(model.errorMsg!!)
}
}
override fun showLoadingFileDialog() {
showFileDialog()
}
override fun hideLoadingFileDialog() {
hideFileDialog()
}
override fun onProgress(totalSize: Long, downSize: Long) {}
}
4. The BaseObserver code is as follows:

/**
* @ Author: njb
* @ : 2020/12/3 17:29
* @ Description:
*/
abstract class BaseObserver <T> : DisposableObserver<T?>{
private var view: BaseView?
private var isShowDialog = false
constructor(view: BaseView?) {
this.view = view
}
constructor(view: BaseView?, isShowDialog: Boolean) {
this.view = view
this.isShowDialog = isShowDialog
}
override fun onStart() {
if (isShowDialog) {
view!!.showLoading()
}
}
override fun onNext(o: T) {
onSuccess(o)
}
override fun onError(e: Throwable) {
if (isShowDialog) {
view!!.hideLoading()
}
val be: BaseException
Onerror ("Error")
}
override fun onComplete() {
if (isShowDialog) {
view!!.hideLoading()
}
}
abstract fun onSuccess(o: T)
abstract fun onError(msg: String?)
}
5.BaseView code is as follows:
/**
* @ Author: njb
* @ : 2020/12/3 15:36
* @ Description:
*/
interface BaseView {
/**
* Show Dialog
*/
fun showLoading()
/**
* Display download file Dialog
*/
fun showLoadingFileDialog()
/**
* Hide Download Document Dialog
*/
fun hideLoadingFileDialog()
/**
* Download progress
* @param totalSize
* @param downSize
*/
fun onProgress(totalSize: Long, downSize: Long)
/**
* Hide Dialog
*/
fun hideLoading()
/**
* Display error message
* @param msg
*/
fun showError(msg: String)
/**
* error code
*/
fun onErrorCode(baseResult: BaseResult<Any>)
}
6.Apiretrofit code as follows:

/**
* Author: njb
* Time: 2016/12 / 27.13: 56
* Description:
* Source:
*/
class ApiRetrofit {
private val retrofit: Retrofit
private val client: OkHttpClient
val apiService: ApiServer
private val TAG = "ApiRetrofit"
/**
* Request to access Quest
* Response interceptor
*/
private val interceptor = Interceptor { chain ->
val request = chain.request()
val startTime = System.currentTimeMillis()
val response = chain.proceed(chain.request())
val endTime = System.currentTimeMillis()
val duration = endTime - startTime
val mediaType = response.body!!.contentType()
val content = response.body!!.string()
Log.e(TAG, "| Response:$content")
response.newBuilder()
.body(ResponseBody.create(mediaType, content))
.build()
}
private val headInterceptor = Interceptor { chain ->
var request = chain.request()
// Get the method
val method = request.method
if (method == "GET") {
val httpUrlurl = request.url
val url = httpUrlurl.toString()
val index = url.indexOf("?")
if (index > 0) {
//url = url + "&APP_KEY=" + AppConstant.APP_KEY;
} else {
// URL = URL + "? APP_KEY =" + AppConstant.app_key; // Splicing new URL
}
Request = Request.newbuilder (). URL (URL) .build () // Re-build request
} else if (method == "POST") {
val requestBuilder = request.newBuilder()
// Request to be customized: Unified Add token parameters
if (request.body!!.contentLength() == 0L) {
// No parameters
val newFormBody = FormBody.Builder()
requestBuilder.method(request.method, newFormBody.build())
} else if (request.body is FormBody) {
// Normal POST
val newFormBody = FormBody.Builder()
val oidFormBody = request.body as FormBody?
for (i in 0 until oidFormBody!!.size) {
newFormBody.addEncoded(oidFormBody.encodedName(i), oidFormBody.encodedValue(i))
}
requestBuilder.method(request.method, newFormBody.build())
}
request = requestBuilder.build()
}
chain.proceed(request)
}
companion object {
private var apiRetrofit: ApiRetrofit? = null
@JvmStatic
val instance: ApiRetrofit?
get() {
if (apiRetrofit == null) {
synchronized(Any::class.java) {
if (apiRetrofit == null) {
apiRetrofit = ApiRetrofit()
}
}
}
return apiRetrofit
}
}
init {
Client = okhttpclient.builder () // Add log interceptor
.addInterceptor(interceptor)
.addInterceptor(headInterceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS) // .sslSocketFactory()
.build()
retrofit = Retrofit.Builder()
.baseUrl(Constant.BASE_SERVER_URL)
.addConverterFactory(GsonConverterFactory.create())
.addConvertory (SCALARSCONVERTERFAACTORY ()) // supports RXJAVA2
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build()
apiService = retrofit.create(ApiServer::class.java)
}
}
7.ApiServer: Here is WANANDROIDAPI as an example

interface ApiServer {
// Home Article list
@GET("/article/list/{page}/json")
fun articleList(@Path("page") page:Int) : Observable<BaseResult<ArticleListBean>>
@GET("/article/list/{page}/json")
fun articleLists(@Path("page") page:Int) : Call<List<ArticleListBean>>
// Home Advertising
@GET("/banner/json")
fun banner():Observable<BaseListResult<BannerBean>>
// Search hot words
@GET("/hotkey/json")
fun hotkey(): Observable<BaseListResult<HotkeyBean>>
// System interface
@GET("/tree/json")
fun tree(): Observable<BaseListResult<KnowledgeBean.DataBean>>
// article under the knowledge system
@GET("article/list/{page}/json")
fun article(@Path("page") page: Int,@Query("cid") cid: Int): Observable<BaseResult<ArticleListBean>>
// Navigation
@GET("/navi/json")
fun navi():Observable<BaseListResult<NavigationBean.DataBean>>
//category
@GET("/project/tree/json")
fun projectTree(): Observable<BaseListResult<ProjectTitleBean.DataBean>>
// list under project classification
@GET("/project/list/{page}/json")
fun projectList(@Path("page") page: Int,@Query("cid") cid:Int): Observable<BaseBean<ProjectListBean>>
//log in
@POST("/user/login")
@FormUrlEncoded
fun login(@Field("username") username: String, @Field("password") password:String):Observable<BaseBean<LoginBean>>
// Register
@POST("/user/register")
@FormUrlEncoded
fun register(@Field("username") username: String, @Field("password") password: String, @Field("repassword") repassword: String) : Observable<BaseBean<RegisterBean>>
// Collect articles list
@GET("/lg/collect/list/0/json")
fun collect():Observable<BaseBean<*>>
// Collection of articles
@POST("/lg/collect/1165/json")
@FormUrlEncoded
fun collectLg(@Path("id") id:Int):Observable<BaseBean<*>>
/ / Collection of external articles
@POST("/lg/collect/add/json")
@FormUrlEncoded()
fun collectadd():Observable<BaseBean<*>>
// Remove
@POST("/lg/uncollect_originId/2333/json")
@FormUrlEncoded
fun uncollect(@Path("id") id:Int):Observable<BaseBean<*>>
//my collection
@POST("/lg/uncollect/2805/json")
@FormUrlEncoded
fun mycollect(@Path("id") id: Int,@Path("orignId") orignId:Int ) :Observable<BaseBean<*>>
/ / Collection website list
@GET("/lg/collect/usertools/json")
fun usertools():Observable<BaseBean<*>>
// Collection website
@POST("/lg/collect/addtool/json")
@FormUrlEncoded
fun addcollect(@Path("name") name: Int,@Path("link") link: Int):Observable<BaseBean<*>>
// Edit Collection Website
@POST("/lg/collect/updatetool/json")
@FormUrlEncoded
fun updatetool(@Path("id") id: Int,@Path("name") name:Int,@Path("link") liml:Int):Observable<BaseBean<*>>
// Delete the collection website
@POST("/lg/collect/deletetool/json")
@FormUrlEncoded
fun deletetool(@Path("id") id: Int):Observable<BaseBean<*>>
//search for
@POST("/article/query/{page}/json")
@FormUrlEncoded
fun query(@Path("page") page: Int, @Field("k") k:String):Observable<BaseBean<SearchBean>>
// Add a TODO
@POST("/lg/todo/add/json")
@FormUrlEncoded
fun add(@Path("title") title:Int,@Path("content") content:Int,@Path("date") date:Int,@Path("type") type: Int):Observable<BaseBean<*>>
/ / Update a TODO content
@POST("/lg/todo/update/83/json")
@FormUrlEncoded
fun update(@Path("id") id: Int,@Path("title") title: Int,@Path("content") content: Int,@Path("date") date: Int,
@Path("status") status: Int,@Path("type") type: Int):Observable<BaseResult<*>>
/ / Delete a TODO
@POST("/lg/todo/delete/83/json")
@FormUrlEncoded
fun delete(@Path("id") id: Int, @Path("status") status: Int):Observable<BaseResult<*>>
// Unfinished TODO list
@POST("/lg/todo/listnotdo/")
@FormUrlEncoded
fun listnotdo(@Path("type") type: Int,@Path("page")page: Int):Observable<BaseResult<*>>
/ / Toto list
@POST("/lg/todo/listdone/")
@FormUrlEncoded
fun listdone(@Path("type") type:Int,@Path("page") page:Int):Observable<BaseResult<*>>
// only update the completion status Todo
@POST("/lg/todo/done/80/json")
@FormUrlEncoded
fun done(@Path("id") id:Int):Observable<BaseResult<*>>
}
8. Create a View inherited in BaseVew, then create a Presether Inherited in BasePresenter, then inherited in the Activity in BaseActivity, if Fragment is inherited in BaseFragment, the specific implementation code is as follows:

(1) ATRICLISTVIEW: Article list View
/**
* @ Author: njb
* @ : 2020/12/3 17:50
* @ Description:
*/
interface ArticleListView : BaseView {
fun onLoadArtList(date: ArticleListBean)
fun onLoadFriend(date: HotkeyBean)
}
(2) HomePresenter: Article list Presener

/**
* @ Author: njb
* @ : 2020/12/3 17:48
* @ Description:
*/
class HomePresenter(baseView: ArticleListView) : BasePresenter<ArticleListView>(baseView) {
/**
* Article list
*/
fun articleList( page: Int) {
addDisposable(apiServer.articleList(page),object :BaseObserver<BaseResult<ArticleListBean>>(baseView){
override fun onSuccess(o: BaseResult<ArticleListBean>) {
baseView!!.onLoadArtList(o.data!!)
}
override fun onError(msg: String?) {
baseView!!.showError(msg!!)
}
})
}
}
(3) ACTIVITY code:
Use Presener !!. Articles, ArticleList (1) initiating a request, here you only need to pass the parameters, you can see that the network request operation has been put in the PresermTer, and Activity does not make requests and logic operations, just responsible for initiating the request and then according to according to according to according to Returns the result to display the data to do appropriate processing, etc.

class MainActivity : BaseActivity<HomePresenter>(), (ArticleListView) {
override val layoutId: Int
get() = R.layout.activity_main
override fun createPresenter(): HomePresenter {
return HomePresenter(this)
}
override fun initView() {
presenter!!.articleList(1)
}
override fun addListener() {
startA(HomeActivity::class.java)
}
override fun onLoadArtList(date: ArticleListBean) {
Log.d("--data--", date.datas.toString())
}
override fun onLoadFriend(date: HotkeyBean) {
}
override fun showLoading() {
}
override fun hideLoading() {
}
}
(4) Article list entity class: ArticlelistBean
class ArticleListBean {
var datas: MutableList<DatasBean>? = null
class DatasBean {
/**
* apkLink :
* author : Jetictors
* chapterId : 232
* ChapterName: Getting Started and Knowledge Point
* collect : false
* courseId : 13
* desc :
* envelopePic :
* fresh : true
* id : 3226
* link : http://www.cnblogs.com/Jetictors/tag/Kotlin/
* nicedate: 4 hours ago
* origin :
* projectLink :
* publishTime : 1533522956000
* superChapterId : 232
* superChapterName : Kotlin
* tags : []
* Title: Kotlin series articles
* type : 0
* userId : -1
* visible : 1
* zan : 0
*/
Var APKLINK: STRING? = null // article URI
var author: String? = null //
var chapterId: Int = 0 //
var chapterName: String? = null
var isCollect: Boolean = false
var courseId: Int = 0
var desc: String? = null
var envelopePic: String? = null
var isFresh: Boolean = false
var id: Int = 0
var link: String? = null
var niceDate: String? = null
var origin: String? = null
var projectLink: String? = null
var publishTime: Long = 0
var superChapterId: Int = 0
var superChapterName: String? = null
var title: String? = null
var type: Int = 0
var userId: Int = 0
var visible: Int = 0
var zan: Int = 0
var tags: List<*>? = null
var isSelect: Boolean = false
}
}
9. The request results are as follows: You can see the interface data successfully obtained by the following screenshots.


10. So far, Kotlin + Retrofit + RXJAVA + MVP's simple package network request has been completed, the next article summarizes the simple use and encapsulation of Kotlin + Retrofit + RXJAVA + MVVM, followed by JetPack implementation. Welcome friends They came to beat, if there is a problem, I will correct it in time.
Previously, the company's project used the MVP+Retrofit+RxJava framework for network requests, so I am writing an article today to summarize. I believe many people have heard of MVP, Retrofit, and RxJ...
These days, I often use the MVP framework to write projects. Today, I will use the MVP framework for everyone. RxJava+Retrofit requests network data, and recycleView loads, and Fresco images load. MVP...
1. Network loading interface Second.view layer Three.Model layer (processing data, here is the network encapsulation class) 4. Presenter layer Five. In the Activity layer...
It is divided into two parts. The first part is the use of RxJava+Retrofit network request, and the other part is MVP mode combined with network request. First, the use of RxJava+Retrofit Intro...
Dependent configuration kotlin version Implementation In order to make the code in Activity and Fragment simple, and reduce the code invasion caused by business or data acc...
Pilot dependence Then the retrofit tool class Followed by the address class Api Then the interface of the stitched address Followed by MVP M layer First write an M layer interface IModel. Here are som...
First write a tool class: @GET Observable get(@Url String url); Network Request Encapsulation: MVP framework; Write three interfaces: IModel void get(String url,Class aClass,NewCallBack newCallBack); ...
preface: before jacketed request based MVP of the network frame, is okhttp package, due later retrofit, rxJava popular, it is used to change a part of Interpretation: retrofit: a request frame again o...
Dependency required by network request Model interface includes two methods that can be implemented Model class to start processing data An entity class of Presenter can be inherited Presenter is resp...