最近看了下Kotlin。随便找了个简单的地址就开始了copy。真的是copy,代码结构,布局,图片等都是copy的。
本文地址: http://blog.csdn.net/qq_25806863/article/details/73209612
主要是为了体验一下Kotlin在Android开发中是什么样子的。
copy对象就是几百个Gank的其中一个:https://github.com/onlyloveyd/GankIOWithKotlin
也可以他博客看一下 http://blog.csdn.net/poorkick/article/details/72510645
非常感谢大神的分享,copy的结果就是:https://github.com/wangyisll/gankapplication/tree/master
图什么就不放了,跟原来那个一样,就是颜色变了一下
因为使用了Kotlin Android Extensions,所以我觉得没必要再用ButterKnife了,所以就删掉了。
哈哈,下面记录一下copy中感受到的不同,都只是一部分示例,更多的可以看代码进行比较。
这是大神的java版 https://github.com/onlyloveyd/GankIOClient
这是大神的kotlin版 https://github.com/onlyloveyd/GankIOWithKotlin
具体语法还是看官方语法文档吧。
1.Kotlin Android Extensions
这是Kotlin官方的扩展,可以省去finViewById
如在activity_main.xml
中有这样的布局:
上面的id为toolBar
,所以在代码中可以直接使用id来表示这个空间,跟ButterKnife一样。
先引入:
import kotlinx.android.synthetic.main.activity_main.*
然后就能直接在代码中使用了:
setSupportActionBar(toolBar)
2.对属性的引用
在Kotlin中,控件的大部分get和set的属性都能直接向下面这样用:
tvTitle.setText("a")
//写成
tvTitle.text = "a"
3.单例
在原来的额网络请求类单例是这样的:
public class HttpMethods {
public static final String BASE_URL = "http://gank.io/api/";
private static final int DEFAULT_TIMEOUT = 5;
private Retrofit retrofit;
private ContentService contentService;
private OkHttpClient mOkHttpClient;
//构造方法私有
private HttpMethods() {
//手动创建一个OkHttpClient并设置超时时间
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
mOkHttpClient = httpClientBuilder.build();
retrofit = new Retrofit.Builder().client(mOkHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();
contentService = retrofit.create(ContentService.class);
}
//获取单例
public static HttpMethods getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* 用于获取干货数据
*
* @param subscriber 由调用者传过来的观察者对象
* @param category 类别
* @param pagesize 请求数据个数
* @param pagenum 页码
*/
public void getData(Observer subscriber, String category, String pagesize,
int pagenum) {
contentService.getContent(category, pagesize, pagenum)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
。。。
//在访问HttpMethods时创建单例
private static class SingletonHolder {
private static final HttpMethods INSTANCE = new HttpMethods();
}
}
在Kotlin中,单例直接这样写:
object RetrofitClient {
private val retrofit: Retrofit
private val api: RetrofitApiService
private val baseUrl = "http://gank.io/api/"
init {
val httpclient = OkHttpClient.Builder()
httpclient.connectTimeout(10, TimeUnit.SECONDS)
retrofit = Retrofit.Builder().client(httpclient.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseUrl)
.build()
api = retrofit.create(RetrofitApiService::class.java)
}
/**
* 获取干货数据
*/
fun getData(subscriber: Observer, category: String, pageSize: String, pageNum: Int) {
api.getContent(category, pageSize, pageNum)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.safeSubscribe(subscriber)
}
}
class变成了object,然后下面这样使用就是单例的,那些方法就跟变成了static一样,直接调用:
RetrofitClient.getData(...)
4.常量类的定义
java中的常量类一般是这样的:
public class Constant {
public static final long ONE_SECOND = 1000;
public static final long ONE_MINUTE = ONE_SECOND * 60;
public static final long ONE_HOUR = ONE_MINUTE * 60;
public static final long ONE_DAY = ONE_HOUR * 24;
}
在Kotlin中可以写成这样:
object Constant {
val ONE_SECOND: Long = 1000
val ONE_MINUTE = ONE_SECOND * 60
val ONE_HOUR = ONE_MINUTE * 60
val ONE_DAY = ONE_HOUR * 24
}
使用起来都是一样的 Constant.ONE_SECOND
,但是省掉了好多public static final
5.集合的定义
java中集合的初始化是这样的:
public static HashMap sTypeColor = new HashMap() {
{
put("Android", R.drawable.bg_android_tag);
put("iOS", R.drawable.bg_ios_tag);
put("瞎推荐", R.drawable.bg_rec_tag);
put("拓展资源", R.drawable.bg_res_tag);
put("App", R.drawable.bg_app_tag);
put("福利", R.drawable.bg_bonus_tag);
put("前端", R.drawable.bg_js_tag);
put("休息视频", R.drawable.bg_video_tag);
}
};
public static ArrayList sCategoryList = new ArrayList() {
{
add("all");
add("Android");
add("瞎推荐");
add("iOS");
add("前端");
add("拓展资源");
add("App");
add("休息视频");
add("福利");
}
};
在Kotlin中也可以写成类似的:
var sTypeColor: HashMap = object : HashMap() {
init {
put("Android", R.drawable.bg_android_tag)
put("iOS", R.drawable.bg_ios_tag)
put("瞎推荐", R.drawable.bg_rec_tag)
put("拓展资源", R.drawable.bg_res_tag)
put("App", R.drawable.bg_app_tag)
put("福利", R.drawable.bg_bonus_tag)
put("前端", R.drawable.bg_js_tag)
put("休息视频", R.drawable.bg_video_tag)
}
}
var sCategoryList: ArrayList = object : ArrayList() {
init {
add("all")
add("Android")
add("瞎推荐")
add("iOS")
add("前端")
add("拓展资源")
add("App")
add("休息视频")
add("福利")
}
}
更可以写成下面的简单的:
var sTypeColor = mutableMapOf("Android" to R.drawable.bg_android_tag,
"iOS" to R.drawable.bg_ios_tag,
"瞎推荐" to R.drawable.bg_rec_tag,
"拓展资源" to R.drawable.bg_res_tag,
"App" to R.drawable.bg_app_tag,
"福利" to R.drawable.bg_bonus_tag,
"前端" to R.drawable.bg_js_tag,
"休息视频" to R.drawable.bg_video_tag)
var sCategoryList = mutableListOf("all", "Android", "瞎推荐", "iOS", "前端", "拓展资源", "App", "休息视频", "福利")
又省了好多代码....
6.anko的startActivity
启动一个Activity是很常用的,通过anko可以快速启动一个Activity:
先导入,一般都是自动引用
import org.jetbrains.anko.startActivity
然后使用:
startActivity()
也可以带参数:
startActivity("URL" to data.url)
//在WebActivity中接收参数,下面的intent其实就是getIntent(),extras其实就是getExtras()
intent.extras.getString("URL")
7.分支语句
Kotlin中用when代替了switch
用法也是类似的:
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when(item?.itemId){
R.id.refresh -> wv.reload()
R.id.share -> url?.let { share(it) }
R.id.openinbrowse -> url?.let { browse(it) }
R.id.copyurl -> {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.text = url
Snackbar.make(wv,"已复制到剪切板",Snackbar.LENGTH_SHORT).show()
}
}
return super.onOptionsItemSelected(item)
}
而且还能直接作为返回值:
override fun getItem(position: Int): Fragment? {
return when (position) {
0 -> DailyFragment.getInstance()
1 -> SortFragment.getInstance()
2 -> MindFragment.getInstance()
else -> AboutFragment.getInstance()
}
}
8. let的使用和空判断
经常会有这样的需求:
if (dailyBean.getResults().getAndroid() != null) {
mVisitableList.addAll(dailyBean.getResults().getAndroid());
}
判断一个东西不为空,然后执行一段代码。一行可能看不出来,下面这样呢?
@Override
public void onNext(DailyBean dailyBean) {
。。。
if (dailyBean.getResults().getAndroid() != null) {
mVisitableList.addAll(dailyBean.getResults().getAndroid());
}
if (dailyBean.getResults().getApp() != null) {
mVisitableList.addAll(dailyBean.getResults().getApp());
}
if (dailyBean.getResults().getBonus() != null) {
mVisitableList.addAll(dailyBean.getResults().getBonus());
}
if (dailyBean.getResults().getIOS() != null) {
mVisitableList.addAll(dailyBean.getResults().getIOS());
}
if (dailyBean.getResults().getJs() != null) {
mVisitableList.addAll(dailyBean.getResults().getJs());
}
if (dailyBean.getResults().getRec() != null) {
mVisitableList.addAll(dailyBean.getResults().getRec());
}
if (dailyBean.getResults().getRes() != null) {
mVisitableList.addAll(dailyBean.getResults().getRes());
}
if (dailyBean.getResults().getVideo() != null) {
mVisitableList.addAll(dailyBean.getResults().getVideo());
}
。。。
}
如果用let,会少很多,作用是一样的:
override fun onNext(dailyData: DailyData) {
...
dailyData.results.android?.let { mVisitableList.addAll(it) }
dailyData.results.app?.let { mVisitableList.addAll(it) }
dailyData.results.bonus?.let { mVisitableList.addAll(it) }
dailyData.results.ios?.let { mVisitableList.addAll(it) }
dailyData.results.js?.let { mVisitableList.addAll(it) }
dailyData.results.rec?.let { mVisitableList.addAll(it) }
dailyData.results.res?.let { mVisitableList.addAll(it) }
dailyData.results.video?.let { mVisitableList.addAll(it) }
...
}