kotlin-android-extensions 已被弃用,如何使用 @Parcelize?

第 1 步。更新到最新的 kotlin 版本 -1.4.20并替换

apply plugin: 'kotlin-android-extensions'

to

apply plugin: 'kotlin-parcelize'

或者

plugins {
    ..
    id 'kotlin-parcelize'
}

第 2 步。从 android {} 中删除以下代码

androidExtensions {
    experimental = true
}

第 3 步。最后,替换旧的 import ->

import kotlinx.android.parcel.Parcelize

to

import kotlinx.parcelize.Parcelize

新插件:https : //plugins.gradle.org/plugin/org.jetbrains.kotlin.plugin.parcelize

迁移已弃用的 Kotlin Android Extension 使用ViewBinding

最近出现在了一个这样的警告:

The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.

kotlinx.android.synthetic 不再是推荐的做法,删除支持显式findViewById,用ViewBinding替代

ViewBinding

与 Kotlin Extensions相比,它增加了视图查找和类型安全的编译时检查。但视图绑定后,可让您更轻松地编写与视图交互的代码。启用视图绑定后,它会为该模块中存在的每个 XML 布局文件生成一个绑定类。

如何启用视图ViewBinding?

在build.gradle中添加:

android {
..
    buildFeatures {
       viewBinding true
    }
}

如何使用ViewBinding?

  • 如果为模块启用了视图绑定,则会为模块包含的每个 XML 布局文件生成一个绑定类。
  • 每个绑定类都包含对根视图和所有具有 ID 的视图的引用。
  • 绑定类的名称是通过将 XML 文件的名称转换为 Pascal 大小写并Binding在末尾添加单词来生成的。

在Activity中使用ViewBinding

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
}

使用binding对象访问View

binding.name.text = "this is ViewBinding"

在Fragment中使用ViewBinding

在Fragment中使用ViewBinding需要注意,因为ViewBinding不能很好地与Fragment一起使用,如果不在OnDestroy清除,则它不会从内存中清除,导致内存泄漏。

private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = FragmentMainBinding.inflate(inflater, container, false)
    return binding.root
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

像在activity中一样使用对象访问视图

binding.name.text = "this is ViewBinding"

备注

ViewBinding将为模块中的每个XML布局生成一个绑定对象,例如:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

ViewBinding将生成 ActivityMainBinding.java

public final class ActivityMainBinding implements ViewBinding {
  @NonNull
  private final ConstraintLayout rootView;

  @NonNull
  public final TextView textView;
...
}

ViewBinding将为每个具有指定id. 在ActivityMainBinding.java中,ViewBinding生成一个公共inflate方法。
它调用bind将绑定属性的位置,并进行一些错误检查。

Git添加多个远程仓库命令

方法一:默认只能从config中的第一个仓库pull代码

git remote set-url --add gitee https://git.gitee.com/xxxx(仓库地址)

// 此时只需要一次push就能同步到多个远程仓库
git push

方法二:可以选择任一仓库pull

// 添加github
git remote add origin https://github.com/xxx(仓库地址)
// 添加gitee
git remote add gitee https://git.gitee.com/xxxx(仓库地址)

// 删除origin仓库
git remote rm origin

// 提交到github
git push origin 
// 提交到gitee
git push gitee

// 从github更新
git pull origin master
// 从gitee更新
git pull gitee master

GIT忽略而不提交文件的3种情形

1:从未提交过的文件可以用.gitignore 也就是添加之后从来没有提交(commit)过的文件,可以使用.gitignore忽略该文件;
2:已经推送(push)过的文件,想从git远程库中删除,并在以后的提交中忽略,但是却还想在本地保留这个文件,执行:

git rm --cached log/config.xml

log/config.xml要从远程库中删除的文件的路径,支持通配符*

3:已经推送(push)过的文件,想在以后的提交时忽略此文件,即使本地已经修改过,而且不删除git远程库中相应文件 执行:

git update-index --assume-unchanged log/config.xml

log/config.xml 是要忽略的文件的路径。如果要忽略一个目录,打开 git bash,cd到 目标目录下,执行: git update-index --assume-unchanged $(git ls-files | tr 'n' ' ') 比如有一个配置文件记录数据库的链接信息,每个人的链接信息肯定不一样,但是又要提供一个标准的模板,用来告知如何填写链接信息,那么就需要在git远程库上有一个标准配置文件,然后每个人根据自己的具体情况,修改一份链接信息自用,而且不会将该配置文件提交到库。

Room数据库Schema export Error

在使用Android Room数据库的时候报错了:

Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

如果您不需要检查架构并且想要摆脱警告,只需将exportSchema = false添加到RoomDatabase中,如下所示:

@Database(entities = { YourEntity.class }, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
   //...
}

另一种方法是在应用模块的build.gradle文件中,将此文件添加到defaultConfig部分(在android部分下面)。这会将架构写到项目文件夹的schemas子文件夹中。

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

     // ... (applicationId, miSdkVersion, etc)

        kapt {
            arguments {
                arg("room.schemaLocation","$projectDir/schemas".toString())
            }
        }
    }

    buildTypes {
        // ... (buildTypes, compileOptions, etc)
    }
}

//...

以上是Kotlin,如果是Java:

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
            }
        }
    }

    // ... (buildTypes, compileOptions, etc)

}

当执行项目后,在Android Studio 的Project视图下,查看项目,会发现Module生成了一个schemas的文件夹,打开.json文件看起来像这样:

{
 "formatVersion": 1,
 "database": {
   "version": 1,
   "identityHash":"6240057b6178b803a0bf9915edf969e3",
   "entities": [
      {
       "tableName":"sms_table",
       "createSql":"CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT, `date` INTEGER, `client_id` INTEGER)",
       "fields": [
          {
           "fieldPath":"id",
           "columnName":"id",
           "affinity":"INTEGER"
          },
          {
           "fieldPath":"message",
           "columnName":"message",
           "affinity":"TEXT"
          },
          {
           "fieldPath":"date",
           "columnName":"date",
           "affinity":"INTEGER"
          },
          {
           "fieldPath":"clientId",
           "columnName":"client_id",
           "affinity":"INTEGER"
          }
        ],
       "primaryKey": {
         "columnNames": [
           "id"
          ],
         "autoGenerate": true
        },
       "indices": [],
       "foreignKeys": []
      }
    ],
   "setupQueries": [
     "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
     "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, "6240057b6178b803a0bf9915edf969e3")"
    ]
  }
}

改变状态栏文本颜色(WHITE/BLACK)

API> = 23

从API v23及更高版本开始,可以将以下内容添加到AppTheme styles.xml中:

  • 解决方案1
// View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR: 将状态栏的文字设置为黑色
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
  • 解决方案1
<item name="android:statusBarColor">@color/colorPrimaryDark</item>
<item name="android:windowLightStatusBar">true</item>

当android:windowLightStatusBar设置为true,状态栏文字颜色将能够可以看出,当状态栏的颜色是白色的,而当android:windowLightStatusBar设置为false,状态栏文字颜色将被设计在状态栏的颜色是可以看到暗。

API <23

在Android中无法更改状态栏的颜色。可以在应用程序中设置状态栏的背景色

val window: Window = activity.getWindow()
// clear FLAG_TRANSLUCENT_STATUS flag:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
// finally change the color
window.setStatusBarColor(ContextCompat.getColor(activity,R.color.my_statusbar_color))

https://developer.android.google.cn/reference/android/view/Window.html#setStatusBarColor(int)