Kotlin编程开发Android运用程序的相关介绍

  • Kotlin编程之AndroidStudio(包括3.0与2.x版本)配置与使用
  • Kotlin编程开发Android运用程序(Volley+Gson依赖库)
  • Kotlin编程之Kotlin Android Extensions(扩展插件)
  • Kotlin编程之Glide v4 Generated API(Unresolved reference GlideApp)

Kotlin编写MVP案例


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

前期准备

项目中,在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中添加权限:

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

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

开始编写代码

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.Movie>>):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<Movie>){    data class Movie(var year:String,var title:String,var  images: Images){        data class Images(var small:String,var large:String)    }}

加载图片的Glide v4的配置

在上篇已经详细介绍了,请阅读Kotlin编程之Glide v4 Generated API(Unresolved reference GlideApp)。

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 Extensions,请阅读上篇 Kotlin编程之Kotlin Android Extensions(扩展插件).

class 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<MovieList.Movie>) {        //无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.Movie>) : RecyclerView.Adapter.ViewHolder>() {    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()    }}

最终项目结构目录如下:

4. 效果图如下

项目代码:https://github.com/13767004362/KotlinMVPDemo


MVP架构相关的介绍

  • Android Architecture Blueprints(架构蓝图)

  • Android MVP架构

  • Android MVP架构(RxJava+SQLBrite+Retrofit+OkHttp+Glide)

  • Android MVP架构(Volley+CursorLoader+ContentProvider)

更多相关文章

  1. Android设置任何控件透明度
  2. Android查询:模拟键盘鼠标事件(adb shell 实现)
  3. Android数据库代码备忘
  4. android中求区域内两个坐标之间的距离的实现
  5. Android(安卓)Studio(七):项目从Eclipse到Android(安卓)Studio迁
  6. Android(安卓): SeekBar 实现图片旋转缩放
  7. Android(安卓)studio项目不能编译,提示设备版本过低
  8. 用android:clipChildren来实现红心变大特效
  9. Android(安卓)BitmapShader 实战 实现圆形、圆角图片

随机推荐

  1. Android(安卓)Studio目录结构详细解答
  2. ionic4处理android返回按钮事件
  3. android中调用web服务
  4. Android版本更新(适用于6.0/7.0)
  5. Android获取的IMEI只有14位问题解决
  6. Windows7配置Android开发环境
  7. 深入理解Java类加载机制(一)
  8. Android推送通知的实现--PHP+ANDROID做消
  9. [轉]Android的内存泄漏和调试
  10. Android(安卓)中查看内存的使用情况集常