初次尝试用Kotlin实现Android项目
<p style="text-align: center"> </p><p style="text-align: left"> <span style="font-size: 16px">起这个文内标题的原因很简单,就是对Kotlin抱有希望——能使Android的开发更简洁、高效及安全。</span><span style="font-size: 16px">知道Kotlin是从简书的一篇短文,越来越觉得将自己学习、实践的过程和想法总结成文字分享出来,不管文笔好坏,内容多少,若能抛砖引玉就足以。所以,感谢写了那么多精彩文章的大神,而我才刚从山脚启程。</span></p>
<p><span style="font-size: 16px"> 项目源码放在Github上,感兴趣的朋友可以下载,欢迎送星和讨论</span><span style="font-size: 16px">。Demo</span><span style="font-size: 16px">运行的动态效果图如下:</span></p>
<p><img src="http://images2015.cnblogs.com/blog/450484/201612/450484-20161220184405167-1119919372.gif"></p>
<p> </p>
<p><strong><span style="font-size: 18px">1. Kotlin在Android Studio中的环境配置</span></strong></p>
<p><span style="font-size: 16px"> 按照下面两篇文章的介绍操作,就能完成Kotlin在Android Studio中的环境配置(Eclipse就不推荐了),并能学习到基础语法和使用案例。如果有问题可以百度、谷歌或参考分享的项目源码中的Project及App的build.gradle设置,也可以留言大家一起讨论。</span></p>
<p><span style="font-size: 16px"> </span><span style="font-size: 16px">http://kotlinlang.org/docs/tutorials/kotlin-android.html<br></span></p>
<p><span style="font-size: 16px"> </span><span style="font-size: 16px">http://kotlinlang.org/docs/tutorials/android-plugin.html<br></span></p>
<p><span style="font-size: 16px"> 其实和引入普通插件类似,说简单点就是做两件事情:</span></p>
<p><strong> a</strong> 安装Kotlin插件;</p>
<p><strong> b</strong> Porject和App的build.gradle文件中添加引用;</p>
<p> 如果配置没问题了,在Studio工具栏的Code栏最下方会出现可将Java代码转为Kotlin代码的选择项:</p>
<p><img src="http://images2015.cnblogs.com/blog/450484/201612/450484-20161220104307932-320083236.png"></p>
<p> 如果本身就是kt格式,那该选项就是灰色不可点击的。</p>
<p> </p>
<p><span style="font-size: 18px"><strong>2. Kotlin学习与编码总结</strong></span></p>
<p> <span style="font-size: 16px">开发环境OK之后,作为刚接触Kotlin的初学者,有两种选择:</span></p>
<p><span style="font-size: 16px"><strong> a</strong> 直接新建Android项目与Kotlin文件,在学习的同时从无到有得敲Kotlin代码;</span></p>
<p><span style="font-size: 16px"><strong> b</strong> 打开之前的Android项目,通过上述的转化工具先将有一个和若干Java文件转为Kotlin代码,通过阅读转化后的代码可以快速熟悉Android项目的Kotlin的代码;</span></p>
<p><span style="font-size: 16px"> 推荐从第二种方法开始,比较简单,而且一般在将Java代码转过来之后会有一些小错误或者警告,在修改的过程中进步也是蛮大的。</span><span style="font-size: 16px">注明一下:Kotlin不只是能在Android项目中替代Java,在其官网有详细的介绍。</span></p>
<p><span style="font-size: 16px"> 下面着重讲述一下因为Kotlin使得代码变得简洁、安全以及巧妙的几个点,这门新语言日渐成熟,不可能将其特点通过一两篇文章就能覆盖到。随着学习的深入,之后会再进行补充。</span></p>
<p><span style="font-size: 16px"><strong>2.1 text & setText()</strong></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> text1.text = (Editable e)</pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> text1.setText(CharSequence text)</pre>
</div>
<p><span style="font-size: 16px"> 先来个简单的,text1是某布局中TextView组件的id。就这样一句代码,就可以完成文本的设置了,没有TextView类对象声明,不用调用findViewById()查找,是不是简洁好多。虽说这中间有些步骤还是需要Kotlin去默默处理,但是作为开发者,效率明显提升了。一般常用的是后面一种,因为CharSequence或者String的使用频率较高。但是Kotlin的简洁形式都趋向于obj.field,而不是setField()这样的方法,只不过这里将CharSequence转为Editable稍微麻烦了一点:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> text1.text = Editable.Factory().newEditable(message)</pre>
</div>
<p><span style="font-size: 16px"><strong>2.2</strong> <strong>@ & when () {}</strong></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> login_image_sel.setOnClickListener(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">@LoginFragment)
</span><span style="color: rgba(0, 128, 128, 1)">2</span> login_in.setOnClickListener(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">@LoginFragment)
</span><span style="color: rgba(0, 128, 128, 1)">3</span> login_reg.setOnClickListener(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">@LoginFragment)
</span><span style="color: rgba(0, 128, 128, 1)">4</span> login_out.setOnClickListener(<span style="color: rgba(0, 0, 255, 1)">this</span>@LoginFragment)</pre>
</div>
<p><span style="font-size: 16px"> 给四个id代表的组件设置点击监听,方法参数为View.OnClickListener,如果类已经继承了它并实现了其onClick()方法,那么直接写成代表自己的this即可。而@Name部分则是强调类名称(不写也不影响编译、运行),但是写上之后可读性更强了,可以说此@是写成开发者(自己或未来看代码的人)看的。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">override fun onClick(view: View) {
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> val id =<span style="color: rgba(0, 0, 0, 1)"> view.id
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)"> when (id) {
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> R.id.login_image_sel -><span style="color: rgba(0, 0, 0, 1)"> selectImageBtn()
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> R.id.login_in -><span style="color: rgba(0, 0, 0, 1)"> loginInBtn()
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> R.id.login_reg -><span style="color: rgba(0, 0, 0, 1)"> loginRegBtn()
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> R.id.login_out -><span style="color: rgba(0, 0, 0, 1)"> loginOutBtn()
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">else</span> -><span style="color: rgba(0, 0, 0, 1)"> { }
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">10</span> }</pre>
</div>
<p><span style="font-size: 16px"> 第一行需要先解释,Java代码是这样的:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">@Override
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onClick(View view) {}</pre>
</div>
<p><span style="font-size: 16px"> 有几个地方不同:</span></p>
<p><span style="font-size: 16px"><strong> a</strong> @Override->override;</span></p>
<p><span style="font-size: 16px"><strong> b</strong> default->public,Kotlin默认的访问限制是public,所以可以省略;</span></p>
<p><span style="font-size: 16px"><strong> c</strong> void->: Unit,Kotlin无返回值可以省略,也可以写成: Unit,当然看个人习惯了;</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> override fun onClick(view: View): Unit {</pre>
</div>
<p><span style="font-size: 16px"><strong> d</strong> View view->view: View,形参声明形式,具体的后面会再提到;</span></p>
<p><span style="font-size: 16px"> Kotlin用when解放了switch,仔细琢磨一下可以发现,不管是代码形式和行数都简洁了不少。告别了原先Java的case、“:”、break及default,我认为最直接的好处是进入when之后,只会执行匹配项对应的"->"后面那一个分支,不用每次都要小心翼翼地想在哪加break。</span></p>
<p><span style="font-size: 16px"><strong>2.3</strong> <strong>var & val</strong></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> val id = view.id</pre>
</div>
<p><span style="font-size: 16px"> 接着上面的话题,来看一下变量的定义。看到上面这句代码,熟悉脚本语言的朋友会有亲切感,所以有时候觉得Kotlin是在慢慢地将各门语言的优点结合起来。</span></p>
<p><span style="font-size: 16px"> val和var对应,前者定义不可能变量,后者定义可改变量。这时候将Java的final拿出来最合适了,Kotlin中限定不可变的重担是由val来完成,它们限定的变量必须在声明时就赋值(类直接属性除外,具体的后面会再提到)。</span></p>
<p><span style="font-size: 16px"> 那么上面说到方法形参时(view: View),view后面有类型View,其实在声明变量时也是如此,来看几个例子:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> var int1: Int = 1
<span style="color: rgba(0, 128, 128, 1)">2</span> var int2 = 2
<span style="color: rgba(0, 128, 128, 1)">3</span> var str3: String? = <span style="color: rgba(0, 0, 255, 1)">null</span>
<span style="color: rgba(0, 128, 128, 1)">4</span> val str4: String? = <span style="color: rgba(0, 0, 255, 1)">null</span></pre>
</div>
<p><span style="font-size: 16px"> 声明了四个变量:两个可变Int型,一个可变String型,一个不可变String型。既然不可变,那么在后面再次赋值时就会报错了:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> int1 = 2
<span style="color: rgba(0, 128, 128, 1)">2</span> int2 = 3
<span style="color: rgba(0, 128, 128, 1)">3</span> str3 = "Hello"
<span style="color: rgba(0, 128, 128, 1)">4</span> str4 = "Kotlin"//会标红线,鼠标移入显示"Val cannot be reassigned"</pre>
</div>
<p><span style="font-size: 16px"> 实践过就会发现,Kotlin中不能再像Java那样声明变量了,比如:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">var int3
</span><span style="color: rgba(0, 128, 128, 1)">2</span> var int4: Int</pre>
</div>
<p><span style="font-size: 16px"> 这两种都是不行的,会提示"Property must be initialized or be abstract"。</span></p>
<p><span style="font-size: 16px"> 再来看是类型后的那个问号(String? = null),它表示声明的变量是否允许为null。这要和另一种情况区分开:声明变量的时候还不确定其值是什么,解决方式可以是先赋一个不影响程序的值。比如:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> var str3: String = "will be reassigned later"</pre>
</div>
<p><span style="font-size: 16px"> ": String"类型限定部分可以不加,编译器会自动推断,这样处理就没有“?”。</span></p>
<p><span style="font-size: 16px"> 那么有人疑问加“?”和不加的根本区别在哪?就在于程序运行过程中对变量的赋值,如果给没有加“?”的变量赋值了null,程序就会异常。一般用在函数的形参中,比如定义的方法形参如下:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> fun testNotNull(str: String) {}</pre>
</div>
<p><span style="font-size: 16px"> 调用时传给形参str的值是不能为null的,这一特性非常有用。因为在大部分应用场景下都可以确定需要的参数是否可以null,比如读取图像的路径不能为空,通过索引访问元素时列表不能为空等等。这不是说可以完美地解决因为null引起的异常,而是可以将异常的点提前,或者说变量容易发现与消除。至于在不同场景怎么用,还得深入研究,并不是全部限定为NonNull就是最合适的。当然,非空限制在Java代码中也可以通过注解@NonNull来实现。</span></p>
<p><span style="font-size: 16px"> “?”还有一个很有用的地方是方法返回值:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> fun getStringLength(obj: Any): Int?<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (obj is String)
</span><span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 0, 255, 1)">return</span> obj.length <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> no cast to String is needed</span>
<span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span>
<span style="color: rgba(0, 128, 128, 1)">5</span> }</pre>
</div>
<p> 在Java中声明为int返回值类型后,是不允许返回null值的,可能会在没有想要的结果时返回一个标记数值。而在Kotlin中只要检查返回值是否为null,如果不是则返回值就是希望得到的结果。上面的代码还可以简写为:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> fun getStringLength(obj: Any): Int? = if (obj is String) obj.length else null</pre>
</div>
<p><span style="font-size: 16px"> 这里有一个新的知识,is的作用是判断obj是否是String类型实例应用,如果不是则直接返回null,Java是instanceof。</span></p>
<p><span style="font-size: 16px"><strong>2.4</strong> <strong>Any</strong></span></p>
<p><span style="font-size: 16px"> Any有点像Java中的Object,对象的祖先。直接上例子:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> fun showLog(message: Any?<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">2</span> Log.i(LOG_TAG, message?<span style="color: rgba(0, 0, 0, 1)">.toString())
</span><span style="color: rgba(0, 128, 128, 1)">3</span> }</pre>
</div>
<p><span style="font-size: 16px"> 这是在Utils文件中自定义的一个实现log的方法,形参message的类型时Any?,正好巩固一下上一条的概念。对于传入的实参,可以是null,也可以是任意类型的变量值;重点在于message后面的那个“?”,它会判断message是否为null,如果是则直接返回字串“null”,如果不是才去调用toString()方法。注意这里假设传入的实参对象继承或重写了toString(),否则可能会出错。</span></p>
<p><span style="font-size: 16px"><strong>2.5</strong> <strong>Custom View</strong></span></p>
<p><span style="font-size: 16px"> 这里说的并不是熟悉的自定义一个圆形View,然后在xml或者Java中进行使用,而是直接在代码中生成布局与组件,这又是Kotlin的一个优点。来看定制一个Dialog的代码:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> val dialog =<span style="color: rgba(0, 0, 0, 1)"> Dialog(mContext, R.style.DialogNoTitle)
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">dialog.setContentView(mContext.linearLayout {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)"> imageView {
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> Utils.setImageToView(mContext, <span style="color: rgba(0, 0, 255, 1)">null</span>, imageUri, <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)"> onClick {
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)"> dialog.dismiss()
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 128, 1)">10</span>
<span style="color: rgba(0, 128, 128, 1)">11</span> dialog.show()</pre>
</div>
<p><span style="font-size: 16px"> 代码中的Style和Utils部分可以在项目源码中查看,这里主要针对Kotlin定义布局部分。动态添加线性布局和一个图像组件只需要声明一个名称即可,分别为linearLayout和imageView。可以理解为包含的元素以{}为界,imageView属于linearLayout,而onClick {}和this则是属于imageView。测试发现,显示的Dialog默认就是居中的,想达到其他效果进行相应的调整即可。</span></p>
<p><span style="font-size: 16px"><strong>2.6</strong> <strong>Map</strong></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">`object`.map {
</span><span style="color: rgba(0, 128, 128, 1)">2</span> var bulletinT =<span style="color: rgba(0, 0, 0, 1)"> ReceiveBulletin(it.teacherName,
</span><span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 0, 0, 1)"> it.updatedAt,
</span><span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 0, 0, 1)"> it.bulletinContent,
</span><span style="color: rgba(0, 128, 128, 1)">5</span> it.bulletinImage?<span style="color: rgba(0, 0, 0, 1)">.fileUrl)
</span><span style="color: rgba(0, 128, 128, 1)">6</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">do something</span>
<span style="color: rgba(0, 128, 128, 1)">7</span> }</pre>
</div>
<pre><span style="font-size: 16px"> 这里的`object`可以是列表数据,也可以是数组等其他集合类型。map的作用就是遍历集合中的每一个元素,对其在{}中进行处理,而每个元素的临时名称为“it”。这样,是不是又可以不用看到for或者Iterator了。</span></pre>
<p><span style="font-size: 16px"><strong>2.7 Class</strong></span></p>
<p><span style="font-size: 16px"> 2.3中提到过val声明的变量也可以先不赋值,这种情况会在Class的声明时出现:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">class</span> BulletinAdapter(<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> val mContext: Context,
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 255, 1)">private</span> val mBulletins: ArrayList<ReceiveBulletin><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">3</span> : RecyclerView.Adapter<BulletinAdapter.ViewHolder>() {}</pre>
</div>
<p><span style="font-size: 16px"> 自定义了一个和RecyclerView结合使用的Adapter类,类的继承由Java的extends变成了冒号“:”,仿佛进入了C++的世界。</span></p>
<p><span style="font-size: 16px"> 类名后面竟然跟了一个括号“()”,而且还多了那么多奇怪的参数,Kotlin的解释是这样写相当于快捷的构造函数。其实可以理解为primary constructor方法省略了名称,如果方法前有注解等特殊修改,那么名称“constructor”是不能省略的。之所以说类后面跟着的方法为primary,是因为在类中还可以实现secondary constructors,以后用到时再深挖吧。而init是在类对象构造时就会调用一次,仅此一次,所以可以作为类实例时的标记,比如打印log:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">init {
</span><span style="color: rgba(0, 128, 128, 1)">2</span> Utils.showLog("Create a BulletinAdapter object"<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">3</span> }</pre>
</div>
<p><span style="font-size: 16px"> val就不解释了,传入的实参赋给形参变量后,在本类中是不允许改变的。但是集合有点特殊,比如重新给mContext赋值不行,但是给mBulletins通过add()方法添加元素是可以的,这里涉及到对象指向的地址和包含的元素问题,先不展开。</span></p>
<p><span style="font-size: 16px"> 添加了private访问限定符的目的和Java中类似,在类外不可见,即不允许在类外面对变量进行访问与更改。</span></p>
<p><span style="font-size: 16px"><strong>2.8 if () {} else () {}</strong></span></p>
<p><span style="font-size: 16px"> 之前2.2中when分支->后面代码都只有一句,如果有两句呢?先看看if else的情形:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (position == itemCount - 1<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">2</span> itemView.bulletin_divider.visibility =<span style="color: rgba(0, 0, 0, 1)"> View.GONE
</span><span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 0, 255, 1)">else</span>
<span style="color: rgba(0, 128, 128, 1)">4</span> itemView.bulletin_divider.visibility = View.VISIBLE</pre>
</div>
<p><span style="font-size: 16px"> 当分支下有多个语句时,必须将属于分支的所有代码都包含在{}中,否则会出现下面的else匹配不到if的错误,这点和Java中的也是相同的。最后提一下Kotlin中不推荐在语句后写分号“;”,写上也没错,只是给变量名下面画一条灰色的提醒而已。</span></p>
<p><span style="font-size: 16px"><img src="http://images2015.cnblogs.com/blog/450484/201612/450484-20161221155254386-1951565362.png"></span></p>
<p> </p>
<p><span style="font-size: 18px"><strong>3. 总结</strong></span></p>
<p><span style="font-size: 16px"><strong>3.1</strong> <strong>项目介绍</strong></span></p>
<p><span style="font-size: 16px"> 开头给出了项目源码下载地址和运行动态效果图,现在来进行简单的介绍。自己学习过程中练手的不能叫做App,确切地应该叫Demo。</span></p>
<p><span style="font-size: 16px"> Demo一共三个页面:消息接收、消息发送及用户信息。</span></p>
<p><span style="font-size: 16px"><strong> a</strong> 消息接收:</span><span style="font-size: 16px">打开程序时,会从云数据库中读取消息,如果有则加载,没有则显示提示信息(如稍后下拉刷新等);</span><span style="font-size: 16px">一条信息包括发送者头像、名称、发送时间、信息内容(文字或图片至少有其一);</span><span style="font-size: 16px">如果有图片内容,则点击后放大;消息的接收没有用户登录要求;</span></p>
<p><span style="font-size: 16px"><strong> b</strong> 发送消息:</span><span style="font-size: 16px">只有注册并登录的用户才能进行消息的发送;发送的内容至少要有文字或图片内容其中之一;</span></p>
<p><span style="font-size: 16px"><strong> c</strong> 用户信息:</span><span style="font-size: 16px">先进行注册,不能设置数据库中已存在的用户名,一定要选择头像,</span><span style="font-size: 16px">成功后一般会自动登录;</span><span style="font-size: 16px">登陆后才能进行注销操作;</span><span style="font-size: 16px">注销后才能进行再次登录操作;</span></p>
<p><span style="font-size: 16px">这里说的云数据库指的是项目中用到的免费的Bmob云平台,比较适合个人练习用,可以自己建表及定义表中的信息。</span></p>
<p><span style="font-size: 16px"><strong>3.2</strong> <strong>Kotlin未来学习计划</strong></span></p>
<p><span style="font-size: 16px"> 文中提到的和项目中用到的知识点,都只是Kotlin语言的冰山一角。还有更有趣、奇妙的的地方值得去发现,相信以后可以在项目中将以前习以为常的、繁琐的代码进行更简洁、高效的实现。</span></p>
</div>
<div id="MySignature" role="contentinfo">
不要让青春留下太多遗憾,专注<br><br>
来源:https://www.cnblogs.com/tgyf/p/6201837.html
頁:
[1]