Kotlin现在是google推荐的android开发语言,现在尝试着通过写一个Kotlin的应用来学习这门语言,学习的过程也在这里记录。Github项目地址
因为是初次接触Kotlin,如果在文章中有任何错误的地方欢迎指正
内容
Part 1:Kotlin初探(一)基础构建
Part2:Kotlin初探(二)数据加载
APP构建
使用Android Studio3.0(后面简称为AS3)创建一个包含Kotlin以及C++的应用。
后面根据需要配置一下即可。
Gradle配置
project build.gradle 配置用默认的就可以,如果需要使用lambda AS3会提示并自动添加
app build.gradle
//载入插件 使用的是apply函数,apply支持from、plugin、to
//apk 必须加载这个插件
apply plugin: 'com.android.application'
//kotlin插件
apply plugin: 'kotlin-android'
//kotlin绑定控件插件
apply plugin: 'kotlin-android-extensions'
//kotlin 注解处理器
apply plugin: 'kotlin-kapt'
控件绑定插件和注解处理插件不是必须的
dependencies {
implementation project(':gearlibrary')
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.android.support:cardview-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
...
}
这里注意compile被标记过时,通过两个新指令代替
api:完全等同于compile指令,没区别
implementation:对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,
也就是将该依赖隐藏在内部,而不对外部公开,如果你的appModel中有使用依赖那么需要使用api指令对全局开放
框架
因为是刚开始使用kotlin编程,所以只使用了一些常用的框架,业务逻辑框架选择使用MVP,网络使用Retrofit+Okio+Rxjava,图片处理Glide4,Rxjava生命周期Rxlifecycle
这里对activity的分类是按照功能来划分的,主要也是想看一下这样划分与平常activity、adapter、fragment这种划分平常开发中有什么不同。
类说明
后面除了对类说明以外,还会对相关的kotlin语言加以说明
GearApp
app全局初始化,以及自定义属性
class GearApp : Application(){
override fun onCreate() {
super.onCreate()
init()
}
private fun init(){
}
}
1.java继承使用extends关键字,kotlin的继承使用 : 表示,并且父类后面需要加()
2.kotlin是强制使用override关键字,而不是以前java@override
3.fun 表示一个方法,前面可以用可见性修饰符修饰
BaseActivity 、 BasePActivity
RxLifecycleActivity 主要是为Rxjava生命周期服务,它会提供一个常量并绑定到activity的生命周期中,并提供可见的方法以供Rxjava使用。
BaseActivity 一般app都会有这个类集合共有的方法、参数、初始化等
BasePActivity 主要是为MVP的构建方式服务,提供一个延迟初始化的presenter
abstract class BasePActivity> : BaseActivity(){
protected lateinit var mPresenter : T
}
1.var标识变量、val标识常量,如果你的常量需要被java方法调用还需要在val前面增加const关键字,因为java只认为被 const val 标识的参数为java的常量。
2.lateinit 标识为延迟初始化变量,当你的变量不为null但是又不想马上初始化的话,就可以使用这个标识符,需要注意的是延迟初始化的变量需要注明参数类型,不然IDE会报错。
3.既然变量可以延迟初始化,常量也是可以的,使用lazy来标识
val name: String by lazy { "abc" }
val name by lazy { 123 }
4.参数类型在kotlin中可以用: String标识,也可以不写直接赋值kotlin会自动推导。
5.泛型的写法
MVP基础类BaseContract、AbstractPresenter
主要想法是通过这样的结构使得 PresenterA 和 ActivityA 之间通过接口来相互调用和解耦,并且ContractA中的接口后期还可以通过AnnotationProcessor方式直接生成。这样MVP相对于之前的MVC只要多写一个Presenter Class就可以并不会增加太多的影响,当然要注意的试因为这只是一个简单的APP所以M、P的逻辑是合并到一起的。
BaseContract中主要是提供presenter、view接口的公共方法
AbstractPresenter 提供mView引用并在构造方法中初始化
abstract class AbstractPresenter(v : V) {
var mView = v
protected set
}
PresenterDataWrapper 会提供Presenter需要的数据模型
open class PresenterDataWrapper(v : V) : AbstractPresenter(v) {
lateinit var mData : R
protected set
/**
* 处理数据
*/
protected open fun processData(d : R?) {}
/**
* 数据出错
*/
protected open fun errorData(error : String) {}
}
1.kotlin语言为变量自动装箱也就是提供set()\get()方法,那么有时候你可能不需要set或者get开放,那么可以使用protected/private set方式来标识set方法的可见度,而get方法的可见度与该参数的可见度相同。
2.(v : V)相当于java中的构造方法,类型由泛型确定。
当你需要一个构造方法时就需要这样写Class(str: String, num: Int,...)
3.mData 会延迟加载并且类型由R : Any 泛型确定。
4.Any 类似于java的Object,但方法只有三个equals()、hashCode()、toString()。
网络相关NetManager、ApiManager
NetManager 提供全局的okClient和Retrofit引用
class NetManager {
/**
* 初始化Ok引用和Retrofit引用
*/
companion object {
var mClient : OkHttpClient = OkHttpManager.getInstance()
.setHeader("apikey","beae89ef686795322d5a3c48579875d5")
.build()
.client
var mRetrofit : Retrofit = GearHttpServiceManager.build(APIConfig.BASE_URL,mClient)
}
}
1.在kotlin如果需要静态参数需要使用 companion object {...} 的方式,这种方式类似于下面的java code
public final class NetManager {
@NotNull
private static OkHttpClient mClient;
@NotNull
private static Retrofit mRetrofit;
public static final NetManager.Companion Companion = new NetManager.Companion((DefaultConstructorMarker)null);
static {
OkHttpClient var10000 = OkHttpManager.getInstance().setHeader("apikey", "beae89ef686795322d5a3c48579875d5").build().getClient();
Intrinsics.checkExpressionValueIsNotNull(var10000, "OkHttpManager.getInstanc…)\n .client");
mClient = var10000;
Retrofit var0 = GearHttpServiceManager.build("http://120.27.118.74/", Companion.getMClient());
Intrinsics.checkExpressionValueIsNotNull(var0, "GearHttpServiceManager.b…IConfig.BASE_URL,mClient)");
mRetrofit = var0;
}
public static final class Companion {
@NotNull
public final OkHttpClient getMClient() {
return NetManager.mClient;
}
public final void setMClient(@NotNull OkHttpClient var1) {
Intrinsics.checkParameterIsNotNull(var1, "");
NetManager.mClient = var1;
}
@NotNull
public final Retrofit getMRetrofit() {
return NetManager.mRetrofit;
}
public final void setMRetrofit(@NotNull Retrofit var1) {
Intrinsics.checkParameterIsNotNull(var1, "");
NetManager.mRetrofit = var1;
}
private Companion() {
}
}
}
ApiManager提供接口调用方法
object ApiManager {
val travelNotesApi : TravelNotesApi = NetManager.mRetrofit.create(TravelNotesApi::class.java)
}
1.object 标识该类为单例的
会生成java代码:
public final class ApiManager {
@NotNull
private static final TravelNotesApi travelNotesApi;
public static final ApiManager INSTANCE;
@NotNull
public final TravelNotesApi getTravelNotesApi() {
return travelNotesApi;
}
private ApiManager() {
INSTANCE = (ApiManager)this;
Object var10000 = NetManager.Companion.getMRetrofit().create(TravelNotesApi.class);
Intrinsics.checkExpressionValueIsNotNull(var10000, "NetManager.mRetrofit.cre…avelNotesApi::class.java)");
travelNotesApi = (TravelNotesApi)var10000;
}
static {
new ApiManager();
}
}
Next Post:
Kotlin初探(二)数据加载