最近文章

Gradle手动安装说明

环境要求Gradle依赖于JDK8或以上版本。在安装之前,先执行java -version检查JDK版本:>java -version java version "11.0.13" 2021-10-19 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.13+10-LTS-370) Java HotSpot(TM) 64-Bit Ser
标签:

Git查看,修改用户名和邮箱(local和global)

git config命令查看用户名和邮箱#查看用户名 git config user.name #查看邮箱 git config user.emailgit config命令设置用户名和邮箱1. --local对当前仓库设置(仅对当前仓库有效)#设置用户名 git config --local user.name '用户名' #设置邮箱 git config --local user.email
标签:

Git撤销最后一次提交

Git可以使用reset重置来撤销提交。方法一撤销最后一次提交git reset HEAD~1 执行后,状态重置为上一次提交,且撤回提交的文件的状态变回unstaged,即文件没有被git跟踪。示例$ git commit -m 'add test.html' [master ade6d7e] add&nbs
标签:

Kotlin与Java相互调用

Kotlin的设计过程中就考虑到了与Java的互操作性。在Kotlin中可以直接调用既有的Java代码, 反过来在Java中也可以很流畅地使用Kotlin代码。 Kotlin 调用 Java一、大多数Java代码,可以直接调用:fun () { val list = ArrayList<string>() list.add("hello world") }二、
标签:

Flutter移除在Android模拟器上debug banner的方法

Flutter使用Android模拟器时,会有一个debug banner,有以下的方法可以把它移除掉。方法一、在MaterialApp里,把debugShowCheckedModeBanner值设置为false。... return new MaterialApp( title: 'Flutter Test', debugShowCheckedModeBanner: false,
标签:

Maven使用本地jar包

Maven导入本地的jar包,有下面两种方法。方法一:使用mvn安装本地jar包到本地仓库mvn install:install-file \ -Dfile=<path-to-file> \ -DgroupId=<group-id> \ -DartifactId=<artifact-id> \ -Dversion=<version&
标签:

git bash配置代理解决下载慢的方法

首先找到一个代理服务地址,也可以使用shadowsocks,蓝灯。假设本地使用了蓝灯,http(s)代理地址为:127.0.0.1:52427。Git配置代理>git config http.proxy http://127.0.1:52427 >git config https.proxy https://127.0.1:52427Git设置为全局代理git config --glo
标签:

SpringBoot项目集成maven-shade-plugin

因为项目是基于springboot搭建的,按springboot的教程,打包只需要在pom添加以下即可:<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin
标签:

使用ANDROID_ID唯一标识Android设备

使用Settings.Secure#ANDROID_ID 会返回每个用户唯一的64位hex字符串,它是在设备首次boot时生成。我们可以使用它来唯一标识Android设备。import android.provider.Settings.Secure; private String android_id = Secure.getStri
标签:

SpringBoot 打包跳过单元测试的几种方法

SpringBoot打包时要跳过单元测试有几种方法。方法一:在properties定义<skipTests>,设置其值为true。<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEnc
标签:

IntelliJ IDEA新建Groovy项目

目前Groovy稳定版本是Groovy 3.x,开发中的版本是Groovy4。这里以Groovy3作为开发环境。环境要求在使用IntelliJ IDEA新建Groovy项目前,需要确保满足以下的环境要求。1. Groovy3要求安装Java 8+这里不详细说Java 8的安装,检查安装Java安装的版,java -version>java -version java version "14"
标签:

IntelliJ IDEA运行Groovy报错:NoClassDefFoundError: Unable to load class org.apache.groovy.jaxb.extensions.JaxbExtensions due to missing dependency javax/xml/bind/JAXBContext

运行环境IntelliJ IDEA Community 2020.1(社区版)JDK 11Groovy3.0.9报错详情Information:Groovyc: While compiling groovy-tutorial:java.lang.NoClassDefFoundError: Unable to load class org.apache.groovy.jaxb.extensions.
标签:

Android Studio 3.0 Beta4 Dex错误:com.android.dex.DexException: Multiple dex files define

Android Studio切换到3.0 beta4,构建时报dex错误。错误信息:Error:java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to&nb
标签:

Git Warning : LF will be replaced by CRLF

WHAT CR = Carriage Return 即 回车LF = Line Feed 即 换行 Windows 换行使用 CRLF, Linux 和 macOS 则使用 LF 进行换行这是一个历史遗留问题, 没有优劣之分 WHY 在 Windows 下使用 Git 时经常会提示类似的 Warning :The file will have its origin
标签:

解决问题flutter run: No connected devices found; please connect a device, or see flutter.io/setup for getting started instructions.

使用flutter搭建了一个简单的示例,在android studio运行flutter run时提示:No connected devices found; please connect a device, or see flutter.io/setup for getting started instructions.从提示可以看到,原因是flutter没有找到连接的设备或者模拟器。搜索了下,
标签:

Android Studio 3.1 EditText 循环调用导致:StackOverflowError: stack size 8MB

升级到Android Studio 3.1后,原来项目中一个简单的EditText都会报StackOverflowError错误。代码如:<EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height=&qu

Android获取view的绝对坐标

Android提供了两种方法来获取视图的绝对坐标:void getLocationOnScreen (int[] outLocation):获取视图在屏幕的坐标void getLocationInWindow (int[] outLocation):获取视图在Activity窗口的坐标这两个方法都是接收一个数组作为参数,获取的x,y值会存
标签:

使用RecyclerView和LayoutAnimation给列表添加进入动画

这里讲解下使用RecyclerView和LayoutAnimation给列表添加进入动画。分为三个步骤:给列表项添加动画使用列表项的动画定义LayoutAnimationRecyclerView应用LayoutAnimation的动画使用LayoutAnimation定义动画的好处是,它是单独定义,可以应用于任何ViewGroup的子类。这里是以RecyclerView为示例。示例效果示例是一个向
标签:

Android Studio旋转模拟器屏幕的快捷键

Android Studio旋转模拟器屏幕的快捷键:Windows:键盘左下角 Ctrl + F12Mac:Fn + Ctrl + F12Linux:Ctrl + F12
标签:

Android常见的图片压缩方法:质量压缩,尺寸压缩和采样率压缩

这里记录下Android三种常见的图片压缩方法:质量压缩,尺寸压缩和采样率压缩质量压缩采用系统自带的质量压缩算法,将图片压缩成JPEG格式public static Bitmap compressQuality(Bitmap bitmap, int quality) {     ByteArrayOutput
标签:

Android使用InputMethodManager显示和隐藏软键盘

Android主要用InputMethodManager来对软键盘进行管理。手动显示或隐藏软键盘前需要先获取InputMethodManager。InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (imm&
标签:

关闭Android Studio的新特性Instant Run

Android Studio版本:2.3.3File → Settings → Build, Execution, Deployment → Instant Run 在Instant Run的设置界面把Enable Instant Run勾选去掉如图
标签:

Android Gradle Plugin 3.0使用Annotation Processor配置依赖说明

在Android Gradle  3.0之前的版本,compile classpath里的依赖会自动添加到processor classpath,这样在compile classpath里的annotation processor也被添加到processor classpath里,所以插件运行正常。从Android&n
标签:

Android Studio 3.0报错:Error:android-apt plugin is incompatible with the Android Gradle plugin. Please use 'annotationProcessor' configuration instead.

Android Studio 3.0执行android-apt报错:Error:android-apt plugin is incompatible with the Android Gradle plugin.  Please use 'annotation
标签:

Android使用CountDownTimer实现倒计时示例(Kotlin)

CountDownTimer是一个抽象类,它的构造函数为CountDownTimer(long millisInFuture, long countDownInterval) millisInFuture:倒计时的总时间,从调用start()方法开始。毫秒数countDownInterval:倒计时的时间间隔。毫秒数。CountDownTimer主要有四个方法:syn
标签:

Android使用Kotlin新特性Parcelize序列化对象

Android对对象序列化主要有两种方式:Serializable和Parcelable。Serializable实际是使用Java的放射机制对对象做序列化和反序列化,其性能远低于使用Parcelable。但是使用Java写的Parcelable有点繁琐,需要我们实现Parcelable接口,手写很多模板代码。Java版Parcelable示例public class User
标签:

Gradle手动安装说明

更新于 2023.02.28 0分钟阅读 0 评论 5 推荐

    gradle

    作者: Tony
  1. Gradle手动安装说明 Page 1

环境要求

Gradle依赖于JDK8或以上版本。在安装之前,先执行java -version检查JDK版本:

>java -version
java version "11.0.13" 2021-10-19 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.13+10-LTS-370)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.13+10-LTS-370, mixed mode)

安装过程

手动安装Gradle,需要下载安装包。

一、下载最新安装包

Gradle下载地址:https://gradle.org/releases

Gradle提供了两种的安装下载:

  • 二进制版
  • 完整版,完整版包含了文档和源码。你可以根据自己的需要选择下载。

这里以gradle-7.3.3-bin.zip为例做说明。

二、解压压缩包

Windows

创建目录C:\Gradle,接着把gradle-7.3.3-bin.zip解压到C:\Gradle

Linux和MacOS

选在目标目录,解压缩发行版 zip 文件,这里选择/opt/gradle:

$ mkdir /opt/gradle
$ unzip -d /opt/gradle gradle-7.3.3-bin.zip
$ ls /opt/gradle/gradle-7.3.3
LICENSE  NOTICE  bin  getting-started.html  init.d  lib  media

三、配置环境变量

Windows 10

找到编辑环境变量的配置

  • 方法一:在左下角搜索栏输入“环境变量”,选择“编辑系统环境变量”。
  • 方法二:在文件资源管理器中右键单击此电脑(或计算机)图标,然后单击属性 -> 高级系统设置 -> 环境变量。

在系统变量下选择路径,然后单击编辑。为 C:\Gradle\gradle-7.3.3\bin 添加一个条目。点击确定保存:

Linux和MacOS

把Gradle解压后的bin目录配置到PATH 环境变量:

$ export PATH=$PATH:/opt/gradle/gradle-7.3.3/bin

四、验证安装

打开控制台(或 Windows 命令提示符)并运行 gradle -v :

>gradle -v

Welcome to Gradle 7.3.3!

Here are the highlights of this release:
 - Easily declare new test suites in Java projects
 - Support for Java 17
 - Support for Scala 3

For more details see https://docs.gradle.org/7.3.3/release-notes.html


------------------------------------------------------------
Gradle 7.3.3
------------------------------------------------------------

Build time:   2021-12-22 12:37:54 UTC
Revision:     6f556c80f945dc54b50e0be633da6c62dbe8dc71

Kotlin:       1.5.31
Groovy:       3.0.9
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          11.0.13 (Oracle Corporation 11.0.13+10-LTS-370)
OS:           Windows 10 10.0 amd64

Git查看,修改用户名和邮箱(local和global)

发布于 2023.02.27 0分钟阅读 0 评论 5 推荐

    Git操作

    作者: Tony
  1. Git查看,修改用户名和邮箱(local和global) Page 1

git config命令查看用户名和邮箱

#查看用户名
git config user.name
#查看邮箱
git config user.email

git config命令设置用户名和邮箱

1. --local对当前仓库设置(仅对当前仓库有效)

#设置用户名
git config --local user.name '用户名'
#设置邮箱
git config --local user.email '用户邮箱'

2. --global对全局仓库设置

#设置用户名
git config --global user.name '用户名'
git config --global user.email '用户邮箱'

 

 

 

Git撤销最后一次提交

Git可以使用reset重置来撤销提交。

方法一

撤销最后一次提交

git reset HEAD~1

执行后,状态重置为上一次提交,且撤回提交的文件的状态变回unstaged,即文件没有被git跟踪。

示例

$ git commit -m 'add test.html'
[master ade6d7e] add test.html
 1 file changed, 1 insertion(+)
 create mode 100644 test.html
$ git reset HEAD~1
$ git status
On branch master
Untracked files:
 (use "git add <file>..." to include in what will be committed)

    test.html

nothing added to commit but untracked files present (use "git add" to track)

撤回后test.html为Untracked files。

方法二

git reset --soft HEAD~1

使用--soft,执行后,状态重置为上一次提交,但撤回提交的文件add到git,被git跟踪。

示例

$ git commit -m 'add test.html'
[master 877b8f0] add test.html
 1 file changed, 1 insertion(+)
 create mode 100644 test.html

$ git reset --soft HEAD~1

clcaza@clcaza MINGW64 /d/webstormProjectsDemo/ngcli-demo (master)
$ git status
On branch master
Changes to be committed:
 (use "git reset HEAD <file>..." to unstage)

    new file: test.html

test.html状态为Changes to be committed

Kotlin与Java相互调用

Kotlin的设计过程中就考虑到了与Java的互操作性。在Kotlin中可以直接调用既有的Java代码, 反过来在Java中也可以很流畅地使用Kotlin代码。
 

Kotlin 调用 Java

一、大多数Java代码,可以直接调用:

fun () {
    val list = ArrayList<string>()
    list.add("hello world")
}

二、特殊的调用规则

以下为Kotlin调用Java的一些特殊调用规则

  1. 返回值为void的方法, 在 Kotlin 中调用时将返回 Unit。
  2. 符合 Java 的 Getter 和 Setter 规范的方法,在 Kotlin 中会被识别为属性。
  3. 某些 Kotlin 关键字在 Java 中是合法的标识符,如:in、object、is等,在Kotlin中使用时要使用反引号转义,如 `object`。
// Java 代码
public class Person {
    private String name;
    public void speak() {
        System.out.println("My name is " + name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

在Kotlin中调用Java代码

fun callJava() {
    val person = Person()
    person.name = "Haosir"
    person.speak()
}

Java调用Kotlin

可以直接通过 getter / setter 方法对 Kotlin 类的属性取值或赋值;

// Kotlin代码
class AlphaGo(var version: String) {
    fun play() {
        print("AlphaGo $version is play GO")
    }
}

在Java中调用Kotlin代码

public void callKotlin() {
    AlphaGo alphaGo = new AlphaGo("3.0");
    String version = alphaGo.getVersion();
    alphaGo.play();
}

Flutter移除在Android模拟器上debug banner的方法

Flutter使用Android模拟器时,会有一个debug banner,有以下的方法可以把它移除掉。

方法一、在MaterialApp里,把debugShowCheckedModeBanner值设置为false。

...
return new MaterialApp(
    title: 'Flutter Test',
    debugShowCheckedModeBanner: false,
    home: new Column(
        ...
    ),
    builder: (BuildContext context, Widget child) {
        ...
    }
);
...

 

方法二、如果使用了Android Studio,可以在Flutter Inspector的More Actions里把它关闭,选择Hide Debug Mode Banner

如图:

 

Maven使用本地jar包

Maven导入本地的jar包,有下面两种方法。

方法一:使用mvn安装本地jar包到本地仓库

mvn install:install-file \
   -Dfile=<path-to-file> \
   -DgroupId=<group-id> \
   -DartifactId=<artifact-id> \
   -Dversion=<version> \
   -Dpackaging=<packaging> \
   -DgeneratePom=true

其中:

  • <path-to-file>: jar包路径,例如 → c:\kaptcha-2.3.jar
  • <group-id>: jar包的groupId,例如→ com.google.code
  • <artifact-id>: jar包名称 ,例如 → kaptcha
  • <version>: 版本好,例如 → 2.3
  • <packaging>: 打包方式, 例如 → jar

 

方法二:在pom.xml文件里配置maven install-file插件

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-install-plugin</artifactId>
    <version>2.5.2</version>
    <executions>
        <execution>
            <phase>initialize</phase>
            <goals>
                <goal>install-file</goal>
            </goals>
            <configuration>
                <file>lib/yourJar.jar</file>
                <groupId>com.somegroup.id</groupId>
                <artifactId>artefact-id</artifactId>
                <version>x.y.z</version>
                <packaging>jar</packaging>
            </configuration>
        </execution>
    </executions>
</plugin>

注意:需要替换示例中的groupId,artifactId和version。

这两种方法原理都是把本地jar包安装到本地仓库,然后就可以在pom.xml中引入。

<dependency>
    <groupId>com.somegroup.id</groupId>
    <artifactId>artefact-id</artifactId>
    <version>x.y.z</version>
</dependency>

git bash配置代理解决下载慢的方法

首先找到一个代理服务地址,也可以使用shadowsocks,蓝灯。

假设本地使用了蓝灯,http(s)代理地址为:127.0.0.1:52427。

Git配置代理

>git config http.proxy http://127.0.1:52427
>git config https.proxy https://127.0.1:52427

Git设置为全局代理

git config --global http.proxy http://127.0.1:52427
git config --global https.proxy https://127.0.1:52427

Git取消代理设置

git config --global --unset http.proxy
git config --global --unset https.proxy

Git查看config配置

git config --global -e

SpringBoot项目集成maven-shade-plugin

因为项目是基于springboot搭建的,按springboot的教程,打包只需要在pom添加以下即可:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

但需要用到maven-shade-plugin插件打包,在maven-shade-plugin的dependencies添加spring-boot-maven-plugin即可,集成如下:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>2.1.5.RELEASE</version>
    </dependency>
</dependencies>
<configuration>
    <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
    <createDependencyReducedPom>true</createDependencyReducedPom>
    <filters>
        <filter>
            <artifact>*:*</artifact>
            <excludes>
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
            </excludes>
        </filter>
    </filters>
</configuration>
<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>
            <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                    <resource>META-INF/spring.handlers</resource>
                </transformer>
                <transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
                    <resource>META-INF/spring.factories</resource>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                    <resource>META-INF/spring.schemas</resource>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>com.xxx.App</mainClass>
                </transformer>
            </transformers>
        </configuration>
    </execution>
</executions>
</plugin>

使用ANDROID_ID唯一标识Android设备

使用Settings.Secure#ANDROID_ID 会返回每个用户唯一的64位hex字符串,它是在设备首次boot时生成。我们可以使用它来唯一标识Android设备

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.ANDROID_ID); 

需要注意:

  • 这是唯一标识每一个Android的系统安装,而不是Android设备自身的物理id。
  • Android ID在 Android prior to 2.2 (“Froyo”)不可靠,会生成重复的android id。

还有其他一些唯一识别Android设备的方法,相对其他方法,使用ANDROID_ID是比较可靠的。

其他方法参考:Identifying App Installations

SpringBoot 打包跳过单元测试的几种方法

SpringBoot打包时要跳过单元测试有几种方法。

方法一:在properties定义<skipTests>,设置其值为true。

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>

方法二:使用maven-surefire-plugin插件

在pom.xml的build里添加插件如下:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.20.1</version>
    <configuration>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

IntelliJ IDEA新建Groovy项目

目前Groovy稳定版本是Groovy 3.x,开发中的版本是Groovy4。这里以Groovy3作为开发环境。

环境要求

在使用IntelliJ IDEA新建Groovy项目前,需要确保满足以下的环境要求。

1. Groovy3要求安装Java 8+

这里不详细说Java 8的安装,检查安装Java安装的版,java -version

>java -version
java version "14" 2020-03-17
Java(TM) SE Runtime Environment (build 14+36-1461)
Java HotSpot(TM) 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)

2. 下载安装Groovy 3

下载地址:http://groovy-lang.org/download.html

Windows 安装包安装

如图,windows下可以下载安装包,直接安装。

SDK或二进制包安装

1、下载SDK或二进制包,解压到

D:\dev\apache-groovy-sdk-3.0.9

2、设置环境变量

GROOVY_HOME = D:\dev\apache-groovy-sdk-3.0.9

并把它的bin目录添加到PATH中,修改环境变量的Path,增加

%GROOVY_HOME%\bin

3、验证

>groovy -v
Groovy Version: 3.0.9 JVM: 14 Vendor: Oracle Corporation OS: Windows 10

IntelliJ IDEA新建Groovy项目

1、新建项目:File -》New -》Project…

2、在新建项目配置中,选择左侧Goovy,配置Project SDK,和Groovy library。其中Project SDK是安装的JDK,Groovy library是Groovy的安装目录。

配置后的如图:

接着填写项目名,finish即可。

新建后的项目如图:

3、Hello Wolrd

新建一个HelloWorld.groovy文件,直接输入:

println 'Hello World'

对文件右键,即可运行这个脚本文件。

兼容性问题

如果是Java9+,在运行groovy代码时会报以下错误:

java.lang.NoClassDefFoundError: Unable to load class org.apache.groovy.jaxb.extensions.JaxbExtensions due to missing dependency javax/xml/bind/JAXBContext

详情查看:解决缺失JAXB

IntelliJ IDEA运行Groovy报错:NoClassDefFoundError: Unable to load class org.apache.groovy.jaxb.extensions.JaxbExtensions due to missing dependency javax/xml/bind/JAXBContext

运行环境

  • IntelliJ IDEA Community 2020.1(社区版)
  • JDK 11
  • Groovy3.0.9

报错详情

Information:Groovyc: While compiling groovy-tutorial:java.lang.NoClassDefFoundError: Unable to load class org.apache.groovy.jaxb.extensions.JaxbExtensions due to missing dependency javax/xml/bind/JAXBContext
at org.codehaus.groovy.vmplugin.v8.Java8.configureClassNode(Java8.java:460)
at org.codehaus.groovy.ast.ClassNode.lazyClassInit(ClassNode.java:273)
at org.codehaus.groovy.ast.ClassNode.getMethods(ClassNode.java:395)
at org.codehaus.groovy.transform.stc.AbstractExtensionMethodCache.scan(AbstractExtensionMethodCache.java:116)
at org.codehaus.groovy.transform.stc.AbstractExtensionMethodCache.getMethods(AbstractExtensionMethodCache.java:97)

原因

原因是Java 9+,是没有安装JAXB,即缺少依赖项 javax/xml/bind/JAXBContext ,无法加载类 org.apache.groovy.jaxb.extensions.JaxbExtensions。

解决方法

  • 方法一:SDK降级到JDK 8
  • 方法二:添加Groovy SDK 提供的 JAXB 依赖添加至 IntelliJ IDEA 项目

这里只说如何Groovy SDK 提供的 JAXB 依赖添加至 IntelliJ IDEA Community项目

File -》 Project Structure,选择Global Libraries:

添加groovy安装目录下的lib/extras-jaxb,如上图。

Android Studio 3.0 Beta4 Dex错误:com.android.dex.DexException: Multiple dex files define

Android Studio切换到3.0 beta4,构建时报dex错误。

错误信息:

Error:java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
Error:com.android.dex.DexException: Multiple dex files define Lcom/google/zxing/integration/android/IntentResult;
 

解决方法

方法一:

在Android Studio

  1. 清理项目,Build -> Clean Project
  2. 清理完项目后,重新构建项目,Build -> Rebuild Project

方法二:

  • 删除项目的./gradle文件夹
  • 删除所有构建目录和gradle缓存
  • 在Android Studio,让缓存失效并重启。File > Invalidate caches / Restart...

Git Warning : LF will be replaced by CRLF

WHAT

CR = Carriage Return 即 回车
LF = Line Feed 即 换行

Windows 换行使用 CRLF, Linux 和 macOS 则使用 LF 进行换行
这是一个历史遗留问题, 没有优劣之分

WHY

在 Windows 下使用 Git 时经常会提示类似的 Warning :

The file will have its original line endings in your working directory.
warning: LF will be replaced by CRLF in XXX.

这个提示虽然对于使用 Git 没有影响, 但会输出很多无用信息

HOW

这个转换取决于 Git 中 core.autocrlf 的配置

1. For Windows

关闭此功能

git config --global core.autocrlf false


关闭提示但不关闭功能

#如果你的主要工作环境是 Windows 的话推荐使用此类方法
git config --global core.autocrlf true
git config --global core.safecrlf false

2. For *nix

关闭此功能
git config --global core.autocrlf false

自动将 CRLF 转换为 LF

git config --global core.autocrlf input

解决问题flutter run: No connected devices found; please connect a device, or see flutter.io/setup for getting started instructions.

使用flutter搭建了一个简单的示例,在android studio运行flutter run时提示:

No connected devices found; please connect a device, or see flutter.io/setup for getting started instructions.

从提示可以看到,原因是flutter没有找到连接的设备或者模拟器。搜索了下,在stackoverflow找到了,定位此问题的一些步骤。

分为两种情况:连接的是真机和连接的是模拟器。

配置连接android真机

一、首先确保android的真机版本为Android 4.1 (API level 16)或以上

二、在android机上把开发者选项以及usb 调试(debug)打开

三、使用USB线把手机连接到电脑时,需要授权电脑可以访问android机

四、执行flutter devices命令,检查Flutter是否能识别出android机

如果一切正常,那么就可以执行flutter run了。

配置连接android模拟器

一、在电脑上打开VM acceleration

二、按Android Studio>Tools>Android>AVD Manager,添加android模拟器,虚拟设备

三、配置虚拟机,推荐选择x86和x86_64的image

四、在Emulated Performanc选项上,选择Hardware - GLES 2.0,用来开启硬件加速

五、启动模拟机,接着就可以执行 flutter run了。


其他

如果还是有问题,可以使用flutter的控制台来尝试:

一、执行flutter emulators,列出所有可用的模拟器

> flutter emulators
6 available emulators:
3.2_QVGA_ADP2_API_22 _-_ Lollipop • 3.2in QVGA (ADP2) • Generic • 3.2 QVGA (ADP2) API 22 - Lollipop
Android_ARMv7a
Android_Accelerated_x86
Nexus S API Google Nexus S API 23
Nexus_S_API_25_1080x1920_Nougart_7.1.1_ • pixel • Google • Nexus S API 25 1080x1920 (Nougart 7.1.1)
Pixel_API_28 • pixel • Google • Pixel API 28

二、指定启动的模拟器,使用步骤一列出的模拟器id

> flutter emulators --launch Pixel_API_28

参考:https://stackoverflow.com/questions/49045393/flutter-run-no-connected-devices

Android Studio 3.1 EditText 循环调用导致:StackOverflowError: stack size 8MB

升级到Android Studio 3.1后,原来项目中一个简单的EditText都会报StackOverflowError错误。

代码如:

<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

当点击EditText,获焦时getTextBeforeCursor方法循环调用,最后导致了堆溢出异常,异常如下:

java.lang.StackOverflowError: stack size 8MB
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)
    at android.view.inputmethod.InputConnectionWrapper.getTextBeforeCursor(InputConnectionWrapper.java:46)

在Stackoverflow上有人说这是Android Studio 3.1 advanced profiling的bug:https://issuetracker.google.com/issues/76404689

解决方法:

禁用advanced profiling:

 Edit Configurations -> Profiling -> 去掉Enable advanced profiling的勾选

如图:

Android获取view的绝对坐标

Android提供了两种方法来获取视图的绝对坐标:

  • void getLocationOnScreen (int[] outLocation):获取视图在屏幕的坐标
  • void getLocationInWindow (int[] outLocation):获取视图在Activity窗口的坐标

这两个方法都是接收一个数组作为参数,获取的x,y值会存放在传入的outLocation参数。

可以对这两个方法封装下,返回一个Point:

public static Point getLocationOnScreen(View view){
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return new Point(location[0], location[1]);
}

使用RecyclerView和LayoutAnimation给列表添加进入动画

这里讲解下使用RecyclerView和LayoutAnimation给列表添加进入动画。分为三个步骤:

  1. 给列表项添加动画
  2. 使用列表项的动画定义LayoutAnimation
  3. RecyclerView应用LayoutAnimation的动画

使用LayoutAnimation定义动画的好处是,它是单独定义,可以应用于任何ViewGroup的子类。这里是以RecyclerView为示例。

示例效果

示例是一个向下掉的进入效果,如图:

定义列表项动画

在res/anim/路径下添加文件item_animation_fall_down.xml,它用来定义列表项的动画。添加内容如下:

<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="@integer/anim_duration_medium">

    <translate
        android:fromYDelta="-20%"
        android:toYDelta="0"
        android:interpolator="@android:anim/decelerate_interpolator"
        />

    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:interpolator="@android:anim/decelerate_interpolator"
        />

    <scale
        android:fromXScale="105%"
        android:fromYScale="105%"
        android:toXScale="100%"
        android:toYScale="100%"
        android:pivotX="50%"
        android:pivotY="50%"
        android:interpolator="@android:anim/decelerate_interpolator"
        />

</set>

说明:

  • Translate Y -20%到0%:在动画开始之前,向上移动视图20%的高度,并让它落到最终位置。
  • Alpha 0到1:视图从开始完全不可见,并缓慢出现,直至完全可见。
  • Scale X/Y 105% 到 100%:scale设置为105%,以使其缩小至最终尺寸。 这会使它看起来好像掉下来一样,落到背景上。

定义LayoutAnimation

使用上面定义的每一项的动画来定义LayoutAnimation。在res/anim/添加layout_animation_fall_down.xml文件,它用来定义LayoutAnimation。内容如下:

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/item_animation_fall_down"
    android:delay="15%"
    android:animationOrder="normal"
    />
  • android:animation="@anim/item_animation_fall_down”:定义将哪个动画应用于布局中的每一项。
  • android:delay=”15%":设置动画延迟,0%表示所有项目同时进行动画,100%表示每个项目完成其动画后才开始下一个项目。15%则表示项目动画到达15%时开始下一个项目的动画。
  • android:animationOrder="normal":控制内容的动画顺序,有三种类型:normal,reverse和random。normal表示根据布局的自然顺序(垂直:从上到下,水平:从左到右)出现动画。reverse与normal相反。random表示动画随机出现。

应用LayoutAnimation

有两种方式使用LayoutAnimation:编程方式和xml方式。

编程方式:

int resId = R.anim.layout_animation_fall_down;
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(ctx, resId);
recyclerview.setLayoutAnimation(animation);

xml方式:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"                                        
    android:layoutAnimation="@anim/layout_animation_fall_down"
    />

如果需要更改数据集,可以这样做:

private void runLayoutAnimation(final RecyclerView recyclerView) {
    final Context context = recyclerView.getContext();
    final LayoutAnimationController controller =
            AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_fall_down);

    recyclerView.setLayoutAnimation(controller);
    recyclerView.getAdapter().notifyDataSetChanged();
    recyclerView.scheduleLayoutAnimation();
}

动画二:从右侧滑入

项目动画:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="@integer/anim_duration_long">

    <translate
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromXDelta="100%p"
        android:toXDelta="0"
        />

    <alpha
        android:fromAlpha="0.5"
        android:toAlpha="1"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        />

</set>

LayoutAnimation动画

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/item_animation_from_right"
    android:delay="10%"
    android:animationOrder="normal"
    />

动画三:从底部滑入

项目动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="@integer/anim_duration_long">

    <translate
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromYDelta="50%p"
        android:toYDelta="0"
        />

    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        />

</set>

LayoutAnimation动画

<?xml version=1.0 encoding=utf-8?>
<layoutAnimation
    xmlns:android=http://schemas.android.com/apk/res/android
    android:animation=@anim/item_animation_from_bottom
    android:delay=15%
    android:animationOrder=normal
    />

摘录自:https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213

Android Studio旋转模拟器屏幕的快捷键

Android Studio旋转模拟器屏幕的快捷键:

  • Windows:键盘左下角 Ctrl + F12
  • Mac:Fn + Ctrl + F12
  • Linux:Ctrl + F12

Android常见的图片压缩方法:质量压缩,尺寸压缩和采样率压缩

这里记录下Android三种常见的图片压缩方法:质量压缩,尺寸压缩和采样率压缩

质量压缩

采用系统自带的质量压缩算法,将图片压缩成JPEG格式

public static Bitmap compressQuality(Bitmap bitmap, int quality) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
      return BitmapFactory.decodeStream(bais, null, null);//把ByteArrayInputStream数据生成图片
}

尺寸压缩

根据图片的缩放比例进行等比大小的缩小尺寸

public static Bitmap compressSize(Bitmap bitmap) {
    int ratio = 8;//尺寸压缩比例
    Bitmap result = Bitmap.createBitmap(bitmap.getWidth() / ratio, bitmap.getHeight() / ratio, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(result);
    Rect rect = new Rect(0, 0, bitmap.getWidth() / ratio, bitmap.getHeight() / ratio);
    canvas.drawBitmap(bitmap, null, rect, null);

    return compressQuality(result, 100);
}

最后调用了质量压缩的方法compressQuality

采样率压缩

根据图片的采样率大小进行压缩

public static Bitmap compressSample(String filePath) {
    int inSampleSize = 8;//采样率设置
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;
    Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);

    return compressQuality(bitmap, 100);
}

最后调用了质量压缩的方法compressQuality

Android使用InputMethodManager显示和隐藏软键盘

Android主要用InputMethodManager来对软键盘进行管理。手动显示或隐藏软键盘前需要先获取InputMethodManager。

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
    //...
}

为了避免NullPointException,需要判断imm实例是否为null。

显示软键盘

InputMethodManager显示软键盘有三个方法:

boolean showSoftInput (View view, int flags)
boolean showSoftInput (View view, int flags, ResultReceiver resultReceiver)
void showSoftInputFromInputMethod (IBinder token, int flags)

一般情况下会选择使用第一个方法,即两个参数的showSoftInput,基于两个原因:

  1. showSolftInput的resultReceiver参数用于接收完成输入后返回结果,但由于它可以长时间存在jvm里而不会被gc,使用它需要注意内存泄漏。
  2. showSoftInputFromInputMethod使用不当会存在失效的情况。

所有这里只介绍showSoftInput (View view, int flags)

先上示例

showKeyBoard(View view) {
  InputMethodManager imm = (InputMethodManager) veiw.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
  if (imm != null) {
    view.requestFocus();
    imm.showSoftInput(view, 0);
  }
}

showSoftInput的第一个参数view需要满足以下条件:

  1. 必须是可获取焦点,即view.isFocusable()为true。这里最好的是EditText 或其子类,它默认是可获取焦点的。
  2. 必须以获取焦点,即view.isFocused()为true。为了避免失焦(布局里可能存在多个可获取焦点的控件),可以先使用requestFocus()获得焦点后再调用showSoftInput(),如示例所示。
  3. 当前布局必须加载完成,所以在onCreate调用showSoftInput是会失效。

为了在布局加载完成后再调用showSoftInput,可以使用postDelayed来延迟执行showSoftInput()

getWindow().getDecorView().postDelayed(new Runnable() {
    @Override
    public void run() {
        showKeyBoard(view);//前面例子的方法
    }
}, 100);

showSoftInput第二个参数为flags,它是提供额外操作的标记。目前可以为两个值0和 SHOW_IMPLICIT。SHOW_IMPLICIT表示不是由用户操作引起显示软键盘的,为隐含显示。一般可以使用0。

隐藏软键盘

Android没有与showSoftInput对应的类似hideSoftInput的方法,我们可以使用hideSoftInputFromWindow隐藏软键盘。

方法原型:

boolean hideSoftInputFromWindow (IBinder windowToken, int flags)
  • windowToken:第一个参数可以使用View.getWindowToken()或者getWindow().getDecorView().getWindowToken()
  • flags:隐藏软键盘的标志位,可以传0

关闭软键盘,windowToken不需要已获取焦点的View,所以可以使用getWindow().getDecorView().getWindowToken()获取一个windowToken用于关闭软键盘。

示例

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
    imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}

注意:如果是使用view.getWindowToken(),此view需要被添加到布局里才行,否则不能关闭软键盘。

切换软键盘

InputMehtodManager还提供了toggleSoftInput方法用于切换软键盘显示和隐藏。它不需要向它出入view或windowToken。

方法原型:

void toggleSoftInput (int showFlags, int hideFlags)
  • showFlags:显示使用的标记,和showSoftInput的第二个参数flags一样。
  • hideFlags:隐藏使用的标记,和hideSoftInputFromWindow第二个参数一样。

示例:

 InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm.isActive()) {
    imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); // 隐藏
} else {
    imm.toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY); // 显示
}

关闭Android Studio的新特性Instant Run

Android Studio版本:2.3.3

File → Settings → Build, Execution, Deployment → Instant Run 

在Instant Run的设置界面把Enable Instant Run勾选去掉

如图

Android Gradle Plugin 3.0使用Annotation Processor配置依赖说明

在Android Gradle  3.0之前的版本,compile classpath里的依赖会自动添加到processor classpath,这样在compile classpath里的annotation processor也被添加到processor classpath里,所以插件运行正常。

从Android Gradle Plugin 3.0开始,不再支持自动添加compile classpath里的依赖到processor classpath里的做法,需要我们使用annotationProcessor手动添加依赖。

示例:

dependencies {
    ...
    annotationProcessor 'com.google.dagger:dagger-compiler:<version-number>'
}

Android Gradle 3.0插件仍然会检测依赖的Jar包,如果Jar包里存在META-INF/services/javax.annotation.processing.Processor,那么它就认为这是一个annotation processor,如果在compile classpath里检测到annotation processor,就会导致构建失败。只需要把配置里的compile改为annotationProcessor即可。

如果compile classpath里也需要依赖annotation processor的Jar,那么需要使用compile配置相同的包依赖。

如果在compile classpath里存在你不需要的annotation processor,可以在annotationProcessorOptions 添加配置includeCompileClasspath false来禁用插件对compile classpath里的annotation processor的检查。

如下配置

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                includeCompileClasspath false
            }
        }
    }
}

注意:如果在升级过程中有问题需要回退到Android Studio 2.3,那么可以把includeCompileClasspath设为true,添加compile classpath里的依赖到processor classpath。

Android Studio 3.0报错:Error:android-apt plugin is incompatible with the Android Gradle plugin. Please use 'annotationProcessor' configuration instead.

Android Studio 3.0执行android-apt报错:

Error:android-apt plugin is incompatible with the Android Gradle plugin.  Please use 'annotationProcessor' configuration instead.

原因及解决

Android Gradle 2.2插件集成了android-apt里的所有功能,从Android Gradle 2.3插件开始阻止android-apt的使用。同时android-apt官方停止维护,建议迁移到annotationProcessor。具体查看apt迁移通知From apt to annotationProcessor

迁移方法

1、在build.gradle添加Android Gradle 3.0 插件

buildscript {
    repositories {
        ...
        google()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
    }
}

2、删除build.gradle里android-apt 的相关配置

 buildscript {
     repositories {
         ...
      google()
     }
     dependencies {
         classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
     }
 }
 apply plugin: 'com.neenbedankt.android-apt'

3、替换build.gradle里旧的配置为新的配置

做以下替换

  • compile 改为 implementation,
  • apt 改为 annotationProcessor  
  • testCompile 改为 androidTestImplementation

 dependencies {
   compile 'com.google.dagger:dagger:2.0'
   apt 'com.google.dagger:dagger-compiler:2.0'
 }

改为

 dependencies {
     implementation 'com.google.dagger:dagger:2.0'
     annotationProcessor 'com.google.dagger:dagger-compiler:2.0'
 }

4、清理缓存并重启Android Studio 3.0

Android使用CountDownTimer实现倒计时示例(Kotlin)

CountDownTimer是一个抽象类,它的构造函数为

CountDownTimer(long millisInFuture, long countDownInterval)

millisInFuture:倒计时的总时间,从调用start()方法开始。毫秒数
countDownInterval:倒计时的时间间隔。毫秒数。

CountDownTimer主要有四个方法:

  1. synchronized final void cancel() : 用于取消倒计时
  2. abstract void onFinish() : 倒计时结束后悔调用此方法
  3. abstract void onTick(long millisUntilFinished) : 每一个时间间隔调用一次onTick。
  4. synchronized final CountDownTimer start() :启动倒计时

onFinish()和onTick()为抽象方法,我们可以在里面实现业务代码。

示例代码(kotlin)

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val startButton: Button = findViewById(R.id.startButton)
        val stopButton: Button = findViewById(R.id.startButton)
        val tv: TextView = findViewById(R.id.textView)
        val cdt = MyCountDownTimer(10000,1000, tv)
        startButton.setOnClickListener {
            cdt.start()
        }
        stopButton.setOnClickListener{
            cdt.cancel()
        }
    }

    private inner class MyCountDownTimer(millisInFuture: Long, countDownInterval: Long, internal var tv: TextView) : CountDownTimer(millisInFuture, countDownInterval) {
        override fun onFinish() {
            tv.setText("结束")
        }
        override fun onTick(millisUntilFinished: Long) {
            tv.setText("还剩${millisUntilFinished/1000}秒")
        }
    }
}

Android使用Kotlin新特性Parcelize序列化对象

Android对对象序列化主要有两种方式:Serializable和Parcelable。

Serializable实际是使用Java的放射机制对对象做序列化和反序列化,其性能远低于使用Parcelable。但是使用Java写的Parcelable有点繁琐,需要我们实现Parcelable接口,手写很多模板代码。

Java版Parcelable示例

public class User implements Parcelable{
        private String id;
        private String name;

        public User(String id, String name, String grade){
            this.id = id;
            this.name = name;
       }
       // Getter and setter methods
       .........
       .........

       // Parcelling部分
       public User(Parcel in){
           String[] data = new String[2];

           in.readStringArray(data);
           // 使用数组获取属性的值需要和writeToParcel()写进去的顺序一致
           this.id = data[0];
           this.name = data[1];
       }

       @Оverride
       public int describeContents(){
           return 0;
       }

       @Override
       public void writeToParcel(Parcel dest, int flags) {
           dest.writeStringArray(new String[] {this.id,
                                               this.name});
       }
       public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
           public User createFromParcel(Parcel in) {
               return new User(in); 
           }

           public User[] newArray(int size) {
               return new User[size];
           }
       };
   }

Java版的Parclable,需要重写wirteToParcel方法序列化对象,需要创建以Parcle为参数的构造函数用来对对象反序列化。需要构建Parclable.Creator。

这些代码大多数都是差不多,但我们还是要手写实现。

Kotlin Parcelable特性

Kotlin1.1.4新增了Parcelable特性,添加注解@Parcelize就可以自动生成相应的Parcelable代码。

  上面的例子实现如下:

@Parcelize
data class User(val id: String, val name: String) : Parcelable

相当的简洁!

使用

1、kotlin:>=1.1.4

2、app的build.gradle添加插件

apply plugin: 'kotlin-android-extensions'

3、app的build.gradle下android配置添加

androidExtensions {
    experimental = true
}

基于kotlin的build.gradle示例

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
  compileSdkVersion 26
  defaultConfig {
    ...
  }
  buildTypes {
    ...
  }
  androidExtensions {
    experimental = true
  }
}
dependencies {
  ...
}

4、模型实现Parclable,添加@Parclize

import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
data class User(val name: String, val age: Int) : Parcelable