Android开发问题和经验总结(不断更新中)

安卓常见问题,Bug等以及解答,欢迎大家更新和指正!!!

Android 系统

防止OOM:

8.0之后对内存使用方式做了修改,这两个操作就可以避免全部的oom:
minSdk 26 ndk {abiFilters 'arm64-v8a'}

Android 9 Http请求:Cleartext HTTP traffic to ... not permitted

方案1:改用https

方案2:targetSdkVersion 降到27以下

方案3:更改网络安全配置(1)

1.在res文件夹下创建一个xml文件夹,然后创建一个network_security_config.xml文件,文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

2.接着,在AndroidManifest.xml文件下的application标签增加以下属性:

<application
    android:networkSecurityConfig="@xml/network_security_config"
/>

方案4:更改网络安全配置(2):直接在AndroidManifest.xml配置文件的<application>标签中直接插入android:usesCleartextTraffic="true"

View 问题

TextView

singleLine过时了,使用lines代替。maxLines=“1”不能限制文本只显示一行

string资源字符串自定义部分文本颜色

//string.xml中配置:
<Data><![CDATA[染色<font color="#ff0000">%s</font>染色]]></Data>

//TextView设置:
TextView.setText(Html.fromHtml(getString(id, "format")))

EditText

Java代码中调用了setFilters,会覆盖布局中maxLength属性,除非同时设置了LengthFilter

CheckBox

button属性失效问题

button对应的Selector drawable,把选中和未选中状态单独放到一个drawable中,不然和selected等混在一个文件会失效

RecyclerView

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position...

RecyclerView绑定的 List 对象在更新数据之前进行了 clear,而这时紧接着迅速上滑 RecyclerView,就会造成崩溃,属于RecyclerView内部异常。

RecyclerView在多层嵌套的内容中,即使设置了wrap_content或者match_parent,但是数据项还是只显示1行,Item高度也不是wrap_content

使用可以让RecyclerView显示全的控件进行包裹,推荐使用NestedScrollView。(本人在项目中遇到这个问题,Recyclerview外层是多层LinearLayout, CardView等布局,还要在外层加上下拉刷新的功能。网上多种解决方案都试过,也没有采用inflate(layoutId, null, false)加载Item的方法,因为封装过Adapter再改代价很大。最后的解决方案是:在RecyclerView外层布局包裹NestedScrollView,禁用RecyclerView滑动,使用NestedScrollView的滑动即可[本人使用的下拉刷新是SmartRefreshLayout,内部使用NestedScrollView可以正常滑动,问题解决])

ScrollView嵌套RecyclerView的显示不全,滑动卡顿,夺取了焦点导致页面启动时RecyclerView上方布局没显示问题

有问题的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <!--页面启动时,TextView未显示,焦点被RecyclerView获取-->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="@dimen/_200dp"
                android:gravity="center"
                android:text="Header"
                android:textColor="@color/aero"
                android:textSize="@dimen/_50sp"/>

            <!--没有android:nestedScrollingEnabled="false"时,滑动冲突,-->
            <!--有这个属性时,ScrollView无法滑动,整个ScrollView只能滑动一点-->
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv"
                android:nestedScrollingEnabled="false"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>

        </LinearLayout>
    </ScrollView>
</LinearLayout>

滑动卡顿问题:

recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);
或者
android:nestedScrollingEnabled="false"

RecyclerView夺取焦点问题:外层布局需要增加属性(但是某些时候这个属性不起作用)

android:focusable="true"
android:focusableInTouchMode="true"

RecyclerView夺取焦点问题解决方案2:ScrollView的直接子View使用

//截获RecyclerView焦点
android:descendantFocusability="blocksDescendants" 
//android:descendantFocusability属性:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

显示不全的问题:使用NestedScrollView代替ScrollView

//没有问题的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <!--页面启动时,TextView未显示,焦点被RecyclerView获取-->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="@dimen/_200dp"
                android:gravity="center"
                android:text="Header"
                android:textColor="@color/aero"
                android:textSize="@dimen/_50sp"/>

            <!--没有android:nestedScrollingEnabled="false"时,滑动冲突,-->
            <!--有这个属性时,ScrollView无法滑动,整个ScrollView只能滑动一点-->
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv"
                android:nestedScrollingEnabled="false"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>

        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
</LinearLayout>

LinearLayout嵌套RecyclerView的显示不全,滑动卡顿,夺取了焦点导致页面启动时RecyclerView上方布局没显示问题(真实情况应是ScrollView嵌套LinearLayout嵌套RecyclerView会出现)

附上之前出问题的代码(问题已经改了):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical">

    <include layout="@layout/public_include_title_and_stausview" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:overScrollMode="never"
        android:layout_height="0dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="15dp"
            android:orientation="vertical">

            <LinearLayout
                android:id="@+id/ll_quote_company"
                android:layout_width="match_parent"
                android:orientation="vertical"
                android:layout_height="wrap_content">

                <TextView
                    android:paddingLeft="15dp"
                    android:paddingRight="15dp"
                    android:text="@string/init_quote_top_notice"
                    android:textColor="@color/public_color_FA960C"
                    android:textSize="@dimen/public_font_16sp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

                <android.support.v7.widget.CardView
                    android:layout_margin="@dimen/public_height_12dp"
                    android:layout_width="match_parent"
                    app:cardCornerRadius="10dp"
                    app:cardBackgroundColor="@color/public_bg_3"
                    android:layout_height="wrap_content">

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:paddingLeft="15dp"
                        android:paddingRight="15dp"
                        android:paddingTop="18dp"
                        android:orientation="vertical">

                        <TextView
                            android:layout_width="wrap_content"
                            android:text="@string/quote_company"
                            android:textSize="@dimen/public_font_18sp"
                            android:textColor="@color/public_text_main"
                            android:layout_marginBottom="15dp"
                            android:layout_height="wrap_content" />

                        <include
                            layout="@layout/layout_wabill_detail_line"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content" />

                        <RelativeLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content">

                        <android.support.v7.widget.RecyclerView
                            android:id="@+id/rv"
                            android:layout_width="match_parent"
                            tools:listitem="@layout/item_select_quote"
                            tools:itemCount="1"
                            android:nestedScrollingEnabled="false"
                            app:layoutManager="android.support.v7.widget.GridLayoutManager"
                            app:spanCount="1"
                            android:layout_height="wrap_content" />
                        </RelativeLayout>
                    </LinearLayout>

                </android.support.v7.widget.CardView>

            </LinearLayout>

            <include layout="@layout/layout_quote_order_info" />
        </LinearLayout>
    </ScrollView>

    <RelativeLayout
        android:id="@+id/rl_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/public_bg_3"
        android:padding="@dimen/public_pad_top_10dp">

        <include layout="@layout/layout_btn_left_right" />
    </RelativeLayout>

</LinearLayout>

解决方案是在RecyclerView外包裹RelativeLayout。原因:ScrollView嵌套RecyclerView解决以及原理详解 文中提到LinearLayout和RelativeLayout测量的不同

DiffUtil.Callback RecyclerView动态更新/增减数据需要实现的类

部分(partial)绑定vs完整(full)绑定
payloads 参数 是一个从(notifyItemChanged(int, Object)或notifyItemRangeChanged(int, int, Object))里得到的合并list。
如果payloads list 不为空,那么当前绑定了旧数据的ViewHolder 和Adapter, 可以使用 payload的数据进行一次 高效的部分更新。
如果payload 是空的,Adapter必须进行一次完整绑定(调用两参方法)。

需要实现的方法:DiffUtil.Callback:public Object getChangePayload(int oldItemPosition, int newItemPosition), RecyclerView.Adapter:public void onBindViewHolder(VH holder, int position, List<Object> payloads)

ScrollView

滚动到顶部或者底部 :

scrollView.fullScroll(ScrollView.FOCUS_DOWN);滚动到底部

scrollView.fullScroll(ScrollView.FOCUS_UP);滚动到顶部

滚动到顶部的三种方式:

ScrollView.scrollTo(``0``,``0``);``//直接置顶,瞬间回到顶部,没有滚动过程,其中Y值可以设置为大于0的值,使Scrollview停在指定位置。
ScrollView.fullScroll(View.FOCUS_UP);``//类似于手动拖回顶部,有滚动过程
ScrollView.smoothScrollTo(``0``, ``0``);``//类似于手动拖回顶部,有滚动过程,其中Y值可以设置为大于0的值,使Scrollview停在指定位置。

ViewPager

Item切换重建(主要是和Fragment搭配使用时,切换到第三个页面,第一个页面销毁)

通过setOffscreenPageLimit防止频繁销毁(setOffscreenPageLimit注释:设置当前page左右两侧应该被保持的page数量,超过这个限制,page会被销毁重建(只是销毁视图),onDestroy-onCreateView,但不会执行onDestroy。尽量维持这个值小,特别是有复杂布局的时候,因为如果这个值很大,就会占用很多内存,如果只有3-4页的话,可以全部保持active,可以保持page切换的顺滑

Tools命名空间的使用 xmlns:tools="http://schemas.android.com/tools"

tools命名空间中的各种XML属性,这些属性支持设计时功能(例如,在片段中显示哪种布局)或编译时行为(例如应用于XML资源的缩小模式)。构建应用程序时,构建工具会删除这些属性,因此不会影响APK大小或运行时行为。

错误处理属性

tools:ignore

用于:任何元素

使用者:Lint

此属性接受以逗号分隔的lint问题ID列表,用于忽略指定的错误

例如,忽略MissingTranslation错误:

<string name="show_all_apps" tools:ignore="MissingTranslation">All</string>

tools:targetApi

用于:任何元素

使用者:Lint

此属性与@TargetApiJava代码中的注释相同 :它允许指定支持此元素的API级别(作为整数或代码名称)。

表名此元素(以及任何子元素)将仅在指定的API级别或更高级别上使用。用于阻止lint警告

例如,指定 GridLayout仅适用于API级别14及更高版本:

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    tools:targetApi="14" >

tools:locale

用于: <resources>

使用者:Lint,Android Studio编辑器

这告诉工具给定<resources>元素中的资源的默认语言/语言环境是什么(因为工具否则假定为英语),以避免来自拼写检查器的警告。该值必须是有效的 区域设置限定符

例如,将其添加到values/strings.xml文件(默认字符串值),以指示用于默认字符串的语言是西班牙语而不是英语:

<resources xmlns:tools="http://schemas.android.com/tools"    tools:locale="es">

设计时视图属性——仅在Android Studio布局预览中可见的布局特征

tools: 代替 android:

用于: <View>

使用者:Android Studio布局编辑器

可以使用tools:前缀而不是Android框架中的android:任何<View>属性在布局预览中插入示例数据。当在App运行之前未填充属性的值,但你希望在布局预览中预先看到效果时,这非常有用。

例如,如果android:text属性值是在运行时设置的,或者你希望看到布局的值不同于默认值,则可以添加 tools:text以仅为布局预览指定一些文本。

[图片上传失败...(image-217cda-1594718377962)]

图1.tools:text属性将“Google Voice”设置为布局预览的值

你可以添加android:命名空间属性(在运行时使用)和匹配tools:属性(仅在布局预览中覆盖运行时属性)。或者仅使用tools:属性用于布局预览。例如:

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="First" />

<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Second"
    tools:visibility="invisible"  />

tools:context

用于:任何根 <View>

使用者:Lint,Android Studio布局编辑器

此属性声明默认情况下此布局与哪个Activity相关联。比如导入View.onClick方法到次Activity。

tools:itemCount

用于: <RecyclerView>

使用者:Android Studio布局编辑器

对于给定的RecyclerView,此属性指定布局编辑器应在“ 预览”窗口中呈现的条目数 。

例如:

<android.support.v7.widget.RecyclerView    
    android:id="@+id/recyclerView"    
    android:layout_width="match_parent"    
    android:layout_height="match_parent"    
    tools:itemCount="3"/>

tools:layout

用于: <fragment>

使用者:Android Studio布局编辑器

此属性声明你希望布局预览在Fragment内绘制的布局(因为布局预览无法执行通常应用布局的活动代码)。例如:

<fragment android:name="com.example.master.ItemListFragment"    
    tools:layout="@layout/list_content" />

tools:listitem / tools:listheader / tools:listfooter

用于:( <AdapterView>及其子类,比如<ListView>)

使用者:Android Studio布局编辑器

这些属性指定在列表的条目,页眉和页脚的布局预览中显示的布局。布局中的任何数据字段都填充了数字内容,例如“项目1”,以便列表项不重复。

例如:

<ListView xmlns:android="http://schemas.android.com/apk/res/android"                xmlns:tools="http://schemas.android.com/tools"    
    android:id="@android:id/list"    
    android:layout_width="match_parent"    
    android:layout_height="match_parent"    
    tools:listitem="@layout/sample_list_item"    
    tools:listheader="@layout/sample_list_header"   
    tools:listfooter="@layout/sample_list_footer" />

tools:showIn

用于:布局根<View>需要嵌入并一同显示预览的布局

使用者:Android Studio布局编辑器

此属性将会把当前布局嵌入其引用的布局一同显示预览。例如:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    
    android:text="@string/hello_world"    
    android:layout_width="wrap_content"    
    android:layout_height="wrap_content"    
    tools:showIn="@layout/activity_main" />

资源收缩属性

shrinkResources 的使用参考

minifyEnabled 用来开启删除无用代码,比如没有引用到的代码

shrinkResources 用来开启删除无用资源,也就是没有被引用的文件(经过实测是drawable,layout,实际并不是彻底删除,而是保留文件名,但是没有内容,等等),但是因为需要知道是否被引用所以需要配合mififyEnable使用,只有当两者都为true的时候才会起到真正的删除无效代码和无引用资源的目的。例如:

android {
    ...
    buildTypes {
        release {
            //收缩资源
            shrinkResources true
            //代码混淆
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

tools:shrinkMode

用于: <resources>

使用者:资源缩减构建工具

此属性允许你指定构建工具是否应使用“安全模式”(保护安全并保留所有明确引用的资源以及可能通过调用动态 引用的资源[Resources.getIdentifier()](https://developer.android.com/reference/android/content/res/Resources.html#getIdentifier(java.lang.String, java.lang.String, java.lang.String)))或“严格模式”(仅保留资源)在代码或其他资源中明确引用)。

默认是使用安全模式(shrinkMode="safe")。要改为使用严格模式,需更改为shrinkMode="strict"<resources>节点,如下所示:

<?xml version="1.0" encoding="utf-8"?><resources xmlns:tools="http://schemas.android.com/tools"    tools:shrinkMode="strict" />

启用严格模式时,你可能需要使用tools:keep 以保留已删除但实际需要的资源,并用于 tools:discard显式删除更多资源。

有关更多信息,请参阅 缩小资源

tools:keep

用于: <resources>

使用者:资源缩减构建工具

此属性用于指定你需要保留的资源(通常是因为它们在运行时以间接方式引用,例如通过将动态生成的资源名称传递给 [Resources.getIdentifier()](https://developer.android.com/reference/android/content/res/Resources.html#getIdentifier(java.lang.String, java.lang.String, java.lang.String)))。

用法:在资源目录(例如,at res/raw/keep.xml)中使用<resources>标记创建XML文件, 并将要保留在tools:keep属性中的每个资源指定为以逗号分隔的列表。可以将星号字符用作通配符。例如:

<?xml version="1.0" encoding="utf-8"?><resources xmlns:tools="http://schemas.android.com/tools"    tools:keep="@layout/used_1,@layout/used_2,@layout/*_3" />

tools:discard

用于: <resources>

使用者:资源缩减构建工具

此属性用于指定你需要手动丢弃的资源(通常是因为资源引用但不会影响你的应用,或者因为Gradle插件错误地推断出资源被引用)。

用法:在资源目录(例如,at res/raw/keep.xml)中使用<resources>标记创建XML文件, 并将要保留在tools:discard属性中的每个资源指定为以逗号分隔的列表。可以将星号字符用作通配符。例如:

<?xml version="1.0" encoding="utf-8"?><resources xmlns:tools="http://schemas.android.com/tools"    tools:discard="@layout/unused_1" />

Style问题

declare-styleable

format可选项

"reference"//引用 
"color"//颜色 
"boolean"//布尔值 
"dimension"//尺寸值 
"float"//浮点值 
"integer"//整型值 
"string"//字符串 
"fraction"//百分数,比如200% 
"enum" 枚举值
//enum枚举例子
<attr name="status" format="enum">
    <enum name="content" value="-1"/>
    <enum name="loading" value="0"/>
    <enum name="error" value="1"/>
    <enum name="empty" value="2"/>
</attr>

Activity等系统组件

Activity切换时,短暂白屏问题,主要是启动singleTask或者singleInstance标志的Activity,同时关闭当前Activity,大概率出现这个问题

Activity theme加上 **<item name="android:windowDisablePreview">true</item> ** 即可。

这个标志应该也可以 <item name="android:windowIsTranslucent">true</item> ,然后onCreate应该需要去掉这个标志。

moveTaskToBack(boolean) 点返回键时,把App移到后台,而不是退出

参数为false——代表只有当前activity是task根,指应用启动的第一个activity时,才有效;

参数为true——则忽略这个限制,任何activity都可以有效。

判断Activity是否是task根,Activity本身给出了相关方法:isTaskRoot()

把App移到后台,而不是退出,最简单无脑的使用方法:MainActivity,重写onBackPressed如下,即可实现

    override fun onBackPressed() {
        moveTaskToBack(true)
    }

Activity设置为Dialog样式

方案:

  1. Activity Theme设置为:

    不使用<item name="android:windowIsFloating">true</item>,而使用parent="@style/Theme.AppCompat.DayNight.Dialog"的原因是因为在页面上输入框会被软键盘遮住,软键盘不会顶起输入法

        <style name="ActivityDialogTheme" parent="@style/Theme.AppCompat.DayNight.Dialog">
            <item name="android:windowFrame">@null</item> <!-- 无windowFrame -->
            <!--        <item name="android:windowIsFloating">true</item>  &lt;!&ndash; 浮在activity之上 &ndash;&gt;-->
            <item name="android:windowIsTranslucent">false</item>  <!-- 半透明 -->
            <item name="android:windowNoTitle">true</item> <!-- 隐藏标题 -->
            <item name="windowNoTitle">true</item> <!-- 隐藏标题 -->
            <item name="android:background">@android:color/transparent</item>
            <item name="android:windowBackground">@android:color/transparent</item> <!-- 设置系统给定的透明值 -->
            <item name="android:backgroundDimEnabled">true</item>  <!-- 背景是否变暗-->
        </style>
    
  2. 布局:android:minWidth或者android:layout_width设置为很大的dp,防止宽度太小的问题

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="wrap_content"
            android:minWidth="1000dp"
            android:layout_height="326dp"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:orientation="vertical"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:background="@drawable/bg_hint_dialog_card">
    
            </LinearLayout>
    
        </LinearLayout>
    
    </LinearLayout>
    
    
  3. 防止点击空白处页面关闭,Activity中调用:

    setFinishOnTouchOutside(false);
    

这个方案也有不完美的地方(应该算系统问题),布局较高,输入框靠下时,获取到焦点窗口上移时会被截断。但是不算大问题。

MainActivity打开新的Activity,因点击触发异常后(直接onCreate抛异常App会直接死掉),返回当前Activity时,Fragment重叠问题

新Activity强退,导致MainActivity重新走了生命周期(onCreate-onStart-onResume)Activity保存了Fragment状态,在onCreate中savedInstanceState!=null,里头保存了Fragment状态:

android:support:fragments=android.support.v4.app.FragmentManagerState@ab76c10, android:fragments=android.app.FragmentManagerState@7661309}]

方案:

//方案1:super.onCreate(null); 传null解决
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        //解决Activity重建Fragment重叠问题
        super.onCreate(null);
    }
//方案2:按需清除Bundle中FragmentManagerState

输入法遮挡输入框问题

通用解决方法:AndroidManifest中Activity的windowSoftInputMode属性来调整

通用解决方法无法解决,主要是自定义软键盘的情况

ScrollView中的EditText被自定义输入法遮挡:

ScrollView子控件最后增加一个空布局,比如Space,默认隐藏;界面显示后,计算Space高度:软键盘高度-输入框底部距离当前Activity窗口底部距离,>0时,就是有遮挡问题。

监听自定义软键盘弹出/隐藏,或者输入框是否获得焦点,如果软键盘弹出/输入框获得焦点,显示Space,调用nestedScrollView.scrollTo(0, space.getHeight()),解决遮挡问题;软键盘隐藏时,隐藏Space

Kotlin 专题

Kotlin data class 和 Gson, @parcelize问题

gson 扩展方法

inline fun <reified T> Gson.fromJson(json: String) = fromJson(json, T::class.java)

@parcelize 需要在build.gradle android内设置属性

androidExtensions {
    experimental = true
}

例子:

//正确的data class写法
@Parcelize
data class Student(
    var age: Int = 0,
    var name: String? = null,
    var toy: Toy? = null
) : Parcelable {
}

@Parcelize
data class Toy(
    var price: Int = 0,
    var name: String? = null
) : Parcelable {
}

//错误的data class写法,类体内的name不会序列化,别的地方使用获取到的是null,kotlin bytecode,decompile文件可以看到
@parcelize
data class Student(
    var age: Int = 0): Parcelable {
    var name: String? = null
}


gson解析
val student2 = gson.fromJson<Student>("{\n" +
                    "\t\"age\":10,\n" +
                    "\t\"name\":\"json name\",\n" +
                    "\t\"toy\":{\n" +
                    "\t\t\"name\":\"toy\",\n" +
                    "\t\t\"price\":1000\n" +
                    "\t}\n" +
                    "}", Student::class.java)
            intent.putExtra("student2", student2)

指定Java调用的类名,要用到注解 @file:JvmName(),放在package之前

也就是要写成这样,剩下的就直接改变代码里的类名就可以了。

@file:JvmName("Hello")
package kotlin

@file:JvmName("Utils") 和 @file:JvmMultifileClass 一起使用的场景:

//在需要合并的每个Kotlin文件加入如下属性:
@file:JvmName("Utils")
@file:JvmMultifileClass
demo:

// oldutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package demo

fun foo() {
}

//___________________________________________________________
// newutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package demo
fun bar() {
}

//__________________________________________________________
// build后,在Java文件中的调用方法:
Utils.foo();
Utils.bar();

编写和Kotlin代码文档(相当于Javadoc)

生成文档

Kotlin 的文档生成工具称为 Dokka。其使用说明请参见 Dokka README

Dokka 有 Gradle、Maven 和 Ant 的插件,因此你可以将文档生成集成到你的构建过程中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容