android mvp获取权限,Kotlin项目Android MVP项目(RxJava、Rerotfit、OkHttp、Glide)

Kotlin编写MVP案例

使用Kotlin编程实现一个MVP案例,实现电影列表功能:

AAffA0nNPuCLAAAAAElFTkSuQmCC

前期准备:

项目中,在Gradle中引入框架的配置如下和使用Kotlin Android扩展:apply plugin: 'com.android.application'apply plugin: 'kotlin-android'apply plugin: 'kotlin-android-extensions'//扩展插件dependencies {

compile fileTree(include: ['*.jar'], dir: 'libs')

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

exclude group: 'com.android.support', module: 'support-annotations'

})

compile 'com.android.support:appcompat-v7:25.3.1'

compile 'com.android.support:design:25.3.1'

testCompile 'junit:junit:4.12'

compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"

//Glide v4

compile 'com.github.bumptech.glide:glide:4.0.0-RC0'

annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC0'

//Retrofit 2.x

compile 'com.squareup.retrofit2:retrofit:2.3.0'

compile 'com.squareup.retrofit2:converter-gson:2.3.0'

compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'

//OkHttp 3.x

compile 'com.squareup.okhttp3:okhttp:3.8.0'

compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'

//RxJava 1.x

compile 'io.reactivex:rxjava:1.3.0'

compile 'io.reactivex:rxandroid:1.2.1'}

须注意点:本篇中无findViewById获取控件对象,采用Kotlin Android Extensions方式获取控件对象。

AndroidManifest.xml中添加权限:

除之外,还有各种框架的混淆规则,这里省略不贴。

开始编写代码:

1. 项目通用的BasePrester和BaseView接口:

项目中通用的BasePresenter接口,具备订阅和取消订阅的行为:interface  BasePresenter{    /**

* 订阅

*/

fun subscribe()    /**

* 取消订阅

*/

fun unsubscribe()

}

项目中通用的BaseView接口,具备绑定Presenter的行为:interface BaseView{    /**

* 设置Presenter的方法

*/

fun  setPresenter(presenter: T)

}

2. 开始编写Model中远程数据源

采用Retrofit作为网络异步框架,OkHttp作为传输层。

这里,采用搜索张艺谋的电影,在douban的API中:https://api.douban.com/v2/movie/search?q=张艺谋

Retrofit的请求和响应结果的配置:请求中发送的Body和Header,Respose的接口 :需要添加retrofit:adapter-rxjava库,实现适配器功能interface DouBanService {    /**

*     这里返回一个Observable,用于RxJava结合使用

*/

@GET("{path}")

fun movieList(@Path("path") path:String, @QueryMap options: Map ):Observable

}

Retrofit的操作类:添加OkHttp作为传输层,RxJava适配器,Gson解析的转换器。object RemoteDataSource{

val baseURL="https://api.douban.com/v2/movie/"

val retrofit:Retrofit by lazy {

Retrofit.Builder().baseUrl(baseURL)                .client(OkHttpProvider.createOkHttpClient())                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .build()

}

var douBanService= retrofit.create(DouBanService::class.java)

fun movieList(subscriber:Subscriber>):Subscription{

val url="search"

var map= hashMapOf("q" to "张艺谋" )

var result= douBanService.movieList(url,map).flatMap {

item: MovieList ->Observable.just(item.subjects)

}.subscribeOn(Schedulers.io())        .unsubscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(subscriber)

return result

}

}

OkHttp的配置:需 引入OkHttp库和OkHttp:logging-interceptor库internal class OkHttpProvider{

companion object{        /**

* 自定义配置OkHttpClient

*/

fun createOkHttpClient():OkHttpClient{           var  builder=OkHttpClient.Builder()            var  loggingInterceptor=HttpLoggingInterceptor()

loggingInterceptor.level=HttpLoggingInterceptor.Level.BODY

builder.addInterceptor(loggingInterceptor)            return builder.build()

}

}

}

编写返回的实体类:data  class MovieList(var subjects:List){    data class Movie(var year:String,var title:String,var  images: Images){        data class Images(var small:String,var large:String)

}

}

3. 根据模块业务编写View和Presenter及它的实现类

业务上比较简单,搜索张艺谋的电影,显示在列表上。根据这个分析,写出这个模块的View和Presenter.interface MovieListConstract{

interface Presenter:BasePresenter    /***

* 抽出Presenter对View的响应行为,在View接口中定义

*/

interface View :BaseView{

fun showToast(msg:String)//Toast提示

fun loadMovie(list: List)//加载电影数据

fun showDialog()//显示dialog

fun cancleDialog()//取消dialog

}

}

View的实现类: 在Fragment、Activity、Adapter中怎么使用Kotlin Android Extensionsclass MovieListFragment : Fragment(), MovieListConstract.View {

lateinit var presenters: MovieListConstract.Presenter

lateinit var dialog: ProgressDialog

lateinit var rootView: View

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

rootView = inflater.inflate(R.layout.fragment_movielist, container, false)

return rootView

}

override fun onResume() {

super.onResume()

presenters.subscribe()

}

override fun onPause() {

super.onPause()

presenters.unsubscribe()

}

override fun setPresenter(presenter: MovieListConstract.Presenter) {

this.presenters = presenter

}

override fun showToast(msg: String) {        Toast.makeText(activity.applicationContext, msg, Toast.LENGTH_SHORT).show()

}

/**

* 加载数据

*/

override fun loadMovie(list: List) {

//无findViewById(),直接引用控件

var recyclerView = rootView.movieList_recyclverView

recyclerView.layoutManager = LinearLayoutManager(activity)

recyclerView.adapter = MovieListAdapter(activity, list)

}

override fun showDialog() {

dialog = ProgressDialog(activity)

dialog.show()

}

override fun cancleDialog() {

if (dialog != null && dialog.isShowing) {

dialog.cancel()

}

}

companion object {

//静态对象

val instance = MovieListFragment()

//静态常量

val Tag = MovieListFragment::class.java.javaClass.simpleName

}

}

RecyclerView中Adapter:import kotlinx.android.synthetic.main.movielist_item.view.*/**

* Created by ${新根} on 2017/6/8.

* blog :http://blog.csdn.net/hexingen

*/internal class MovieListAdapter(var context: Context, var list: List) : RecyclerView.Adapter() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =

ViewHolder(View.inflate(parent.context, R.layout.movielist_item, null))

override fun onBindViewHolder(holder: ViewHolder, position: Int) {

GlideUtils.loadUrlImage(context,list[position].images.large,holder.imageView)

holder.title_Tv.text=list[position].title

}

override fun getItemCount() = list.size

internal class ViewHolder(rootView: View) : RecyclerView.ViewHolder(rootView) {        /**

* 这里使用Kotlin Android 扩展,省略了findViewById().

* 在最上面导入了import kotlinx.android.synthetic.main.movielist_item.view.*

*/

var imageView = rootView.movielist_item_iv

var title_Tv= rootView.movielist_item_tv

}

}

Presenter的实现类:class MovieListPresenter(var view: MovieListConstract.View, var compositeSubscription: CompositeSubscription = defaultCompositeSubscription) : MovieListConstract.Presenter {

init {//init初始化模块

view.setPresenter(this)

}    //开始订阅

override fun subscribe() {

view.showDialog()

excuteTask()

}    //执行任务

fun excuteTask() {      var  disposable=RemoteDataSource.movieList(object :Subscriber>() {            override fun onNext(t: List) = view.loadMovie(t)            override fun onError(e: Throwable) {

view.showToast(e.toString())

view.cancleDialog()

}          override fun onCompleted() {

view.showToast("加载完成")

view.cancleDialog()

}

})      this.compositeSubscription.add(disposable)

}    //取消订阅,释放资源

override fun unsubscribe() {

view.cancleDialog()

compositeSubscription.clear()

}

companion object {//采用伴随对象

//默认的值

val defaultCompositeSubscription get() = CompositeSubscription()

}

}

Activity中创建View和Presenter:class MovieListActvitiy : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_movielist)

//创建View实例

var view=MovieListFragment.instance

//创建Presenter实例        MovieListPresenter(view)

//添加fragment

supportFragmentManager.beginTransaction()

.add(R.id.movielist_content_layout,view,MovieListFragment.Tag).commit()

}

}

最终项目结构目录如下:

AAffA0nNPuCLAAAAAElFTkSuQmCC

4. 效果图如下:

AAffA0nNPuCLAAAAAElFTkSuQmCC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值