Android

kotlin 显示 var/val 的真实类型

File —> Settings —> Editor —> Inlay Hints —> Kotlin

勾选 Show local variable type hints

image-20230324101037414

Task :checkDebugDuplicateClasses

这个错误是由于项目中存在重复的类,导致编译失败。你可能需要检查你的依赖树,确保你只使用了一个Kotlin版本。你也可以尝试在gradle中添加这行代码:

id 'org.jetbrains.kotlin.android' version '1.8.0' apply false

安卓组件属性

样式(text Appearance)

  <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem" />
  android:textAppearance="?attr/textAppearanceListItem"

tools:context最通俗的解释

一般在根布局文件中会出现 tools:context = 某个activity名称。

​ 这个属性的意思是:如果你在AndroidManifest.xml文件中为某个activity设置了Theme样式,那么,一般情况下,你在layout布局里面是无法直接看到这个效果的。因为一份layout布局可以提供给很多个activity用,layout无法知道自己提供给了哪个activity,而这个activity又设置了怎样的样式。所以,我们要为layout设置这样一个属性,来告诉layout当前提供给了哪个activity使用,从而实时显示这个activity所设置的样式效果(如果有)。

​ 也就是,layout ----> activity ---->Theme,建立起了链接。否则,即使你为activity设置了样式,你的layout布局文件也是不知道的。

tools:listitem属性

使用 属性 tools:itemCounttools:listitem 给RecyclerView添加直观预览效果

list:

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView 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:id="@+id/list"
    android:name="com.zioplyyc.chat.ChatItem"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    app:layoutManager="LinearLayoutManager"
    tools:context=".ChatItemFragment"
    tools:itemCount="5"
    tools:listitem="@layout/chat_item" />

item:

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

    <TextView
        android:id="@+id/item_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:text="1"
        android:textAppearance="?attr/textAppearanceListItem"
        android:textSize="@dimen/item_id_size" />

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:text="@string/welcome_text"
        android:textAppearance="?attr/textAppearanceListItem"
        android:textSize="@dimen/item_text_size" />
</LinearLayout>

效果预览:

image-20230328111646651

去除标题栏的方法

a、手动在onCreate()里调用下面代码,仅针对单一页面管用:

if (getSupportActionBar() != null){
   getSupportActionBar().hide();
}

b、第二种方法 直接用supportrequestwindowFeature,把1中调用的方法换成下面的就可以了:

   supportRequestWindowFeature(Window.FEATURE_NO_TITLE);

必须加在:setContentView(R.layout.XXXXXXX);前面。

安卓程序去掉标题栏有以下几种方法:

  • 在清单文件 AndroidManifest.xml 中修改主题,使用系统自带的无标题栏样式,如 android:theme=“@android:style/Theme.NoTitleBar” 或 android:theme=“@style/Theme.AppCompat.Light.NoActionBar”
  • 在 style.xml 文件中修改主题,添加 android:windowNoTitle 为 true 的属性,如
    • <item name="android:windowNoTitle">true</item>
  • 在代码中设置窗口特性,使用 requestWindowFeature(Window.FEATURE_NO_TITLE) 方法,需要在 setContentView() 方法之前调用 。

组件的可见性

要检测一个按钮的可见性,您可以使用 View 类的 getVisibility() 方法,它会返回一个整数值,表示按钮的可见性状态。根据 Android 开发者文档1,这些值有三种:

  • View.VISIBLE (0):表示按钮是可见的。
  • View.INVISIBLE (4):表示按钮是不可见的,但仍占用布局空间。
  • View.GONE (8):表示按钮是不可见的,也不占用布局空间。
    因此,您可以使用以下代码来判断一个按钮是否对用户可见:
Button button = findViewById(R.id.button_id);
if (button.getVisibility() == View.VISIBLE) {
    // 按钮是可见的
} else {
    // 按钮是不可见的
}

如果您想在运行时改变按钮的可见性,您可以使用 View 类的 setVisibility(int) 方法,传入相应的值作为参数。例如:

button.setVisibility(View.INVISIBLE); // 设置按钮为不可见
button.setVisibility(View.VISIBLE); // 设置按钮为可见

希望这能帮到您。如果您还有其他问题,请随时提问。

关于线程的启动方式

new Thread(){}.run();

在 Java 中,通过创建一个 Thread 对象并调用其 start() 方法可以启动一个新的线程。但是,如果您调用 Thread 对象的 run() 方法,则该方法会在当前线程中执行,而不会启动一个新的线程。

因此,以下代码将在当前线程中执行,而不会创建新的线程:

typescriptCopy codenew Thread(new Runnable() {
    @Override
    public void run() {
        // 在新线程中执行任务
        // ...
    }
}).run(); // 注意这里调用的是 run() 方法

相反,如果您使用 start() 方法启动线程,则会创建新的线程并在该线程中执行 run() 方法:

typescriptCopy codenew Thread(new Runnable() {
    @Override
    public void run() {
        // 在新线程中执行任务
        // ...
    }
}).start(); // 注意这里调用的是 start() 方法

因此,如果您希望在新线程中执行任务,请使用 start() 方法启动线程。如果调用 run() 方法,则会在当前线程中执行任务,并不会创建新的线程。

单例对象的创建方式

在 Java 中,单例模式是一种常见的设计模式,用于确保类只有一个实例,并提供全局访问点。以下是几种创建单例对象的方式:

  1. 饿汉式单例模式

在这种方式中,单例对象在类加载时就被创建出来,因此线程安全性比较高。但是,如果单例对象比较大,会占用较多的内存空间。

csharpCopy codepublic class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  1. 懒汉式单例模式

在这种方式中,单例对象在第一次使用时被创建出来,因此可以节省内存空间。但是,在多线程环境下需要进行加锁操作,否则会出现线程安全问题。

csharpCopy codepublic class Singleton {
    private static Singleton INSTANCE;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}
  1. 双重校验锁单例模式

在这种方式中,使用双重校验锁来确保线程安全性,同时在第一次使用时创建单例对象。

csharpCopy codepublic class Singleton {
    private static volatile Singleton INSTANCE;

    private Singleton() {}

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton();
                }
            }
        }
        return INSTANCE;
    }
}

需要注意的是,以上几种方式都需要将构造函数设置为私有的,以确保该类不能被外部直接创建实例。同时,单例对象的引用通常被声明为静态变量,并通过一个公共的静态方法获取实例。这样可以保证该单例对象在整个应用程序中只有一个实例,并且可以被全局访问。

键盘状态以及关闭

要获取 Android 设备的当前键盘状态,并且在键盘打开时关闭键盘,可以使用 InputMethodManager 类和 getWindowToken() 方法。

下面是一个示例代码,可以在 Activity 中使用:

// 获取当前键盘状态
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
boolean isKeyboardOpen = inputMethodManager.isAcceptingText();

// 如果键盘打开则关闭键盘
if (isKeyboardOpen) {
    // 获取当前窗口的 token
    View view = this.getCurrentFocus();
    IBinder token = view.getWindowToken();

    // 关闭键盘
    inputMethodManager.hideSoftInputFromWindow(token, 0);
}

首先,我们使用 getSystemService() 方法获取 InputMethodManager 类的实例,这个类是用来控制输入法键盘的。然后,我们调用 isAcceptingText() 方法来判断当前键盘的状态是否为打开状态。

如果键盘打开,我们就需要获取当前窗口的 token,这个 token 是用来标识当前窗口的唯一标识符。然后,我们调用 InputMethodManager 类的 hideSoftInputFromWindow() 方法来关闭键盘。

在这个方法中,第一个参数是当前窗口的 token,第二个参数是一个标志位,用来指定隐藏软键盘时的行为,一般情况下可以传入 0。

工具类

可以将获取键盘状态并关闭键盘的代码封装成一个工具类,以便在应用程序中方便地调用。

下面是一个示例代码,可以作为封装后的工具类使用:

public class KeyboardUtils {
    /**
     * 获取当前键盘状态,并关闭键盘
     * @param activity 当前 Activity
     */
    public static void hideKeyboard(Activity activity) {
        // 获取输入法管理器
        InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager == null) {
            return;
        }

        // 获取键盘状态
        boolean isKeyboardOpen = inputMethodManager.isAcceptingText();

        // 关闭键盘
        if (isKeyboardOpen) {
            View view = activity.getCurrentFocus();
            if (view != null) {
                IBinder token = view.getWindowToken();
                inputMethodManager.hideSoftInputFromWindow(token, 0);
            }
        }
    }
}

在这个工具类中,我们将获取键盘状态并关闭键盘的代码封装在了一个静态方法 hideKeyboard() 中。这个方法需要一个参数 activity,表示当前的 Activity。在这个方法中,我们首先获取输入法管理器的实例,然后判断当前键盘状态是否为打开状态,最后关闭键盘。

获取drawable资源

在 Android 中,setBackground() 方法需要传入一个 Drawable 对象,而不是一个资源 ID。因此,如果想要将一个 Drawable 资源设置为 Activity 的背景,可以使用如下代码:

Drawable drawable = getResources().getDrawable(R.drawable.background_nothing_info);

// 将 Drawable 资源设置为 Activity 的背景
getWindow().setBackgroundDrawable(drawable);

在这个代码中,我们首先使用 getResources().getDrawable() 方法加载一个 Drawable 资源,然后使用 getWindow().setBackgroundDrawable() 方法将该 Drawable 资源设置为 Activity 的背景。注意,setBackgroundDrawable() 方法是在 Window 对象上调用的,因此需要使用 getWindow() 方法获取当前 Activity 的 Window 对象。

需要注意的是,getResources().getDrawable() 方法在 API level 22 中被弃用,推荐使用 ContextCompat.getDrawable() 方法来获取 Drawable 资源。下面是使用 ContextCompat.getDrawable() 方法的示例代码:

// 加载 Drawable 资源
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.background_nothing_info);

// 将 Drawable 资源设置为 Activity 的背景
getWindow().setBackgroundDrawable(drawable);

在这个代码中,我们使用 ContextCompat.getDrawable() 方法来加载 Drawable 资源,并使用 getWindow().setBackgroundDrawable() 方法将该 Drawable 资源设置为 Activity 的背景。注意,ContextCompat.getDrawable() 方法需要传入一个 Context 对象作为第一个参数,这里我们使用 this 关键字来获取当前 Activity 的 Context。

R.string.xxx

在 Android 开发中,R.string.xxx 是一个整数常量,它代表了应用程序资源中一个字符串资源的唯一标识符。这个整数常量是由编译器根据资源文件的名称和位置自动生成的。

在 Android 应用程序中,所有的资源都会被编译成二进制格式并打包进应用程序的 APK 文件中。在应用程序运行时,系统会根据 R.string.xxx 这个整数常量在应用程序的资源池中查找对应的字符串资源,并将其加载到内存中供应用程序使用。

因为 R.string.xxx 是一个整数常量,所以在 Java 代码中使用时,我们需要使用这个整数常量来访问对应的字符串资源。例如,如果我们想要获取一个字符串资源的值,我们可以使用以下代码:

String myString = getString(R.string.my_string);

在这个代码中,R.string.my_string 是一个整数常量,它代表了一个字符串资源的唯一标识符。getString() 方法会根据这个整数常量在应用程序的资源池中查找对应的字符串资源,并返回该字符串资源的值。

getString() 方法属于 Android 应用程序框架中的 Context 类。Context 是一个抽象类,是 Android 应用程序中的一个重要组件,用于访问应用程序的全局信息,如应用程序的资源、应用程序的环境变量等。

在 Android 应用程序开发中,我们通常会在 Activity 或 Fragment 中调用 getString() 方法来获取字符串资源的值,例如:

String myString = getString(R.string.my_string);

在这个代码中,Activity 或 Fragment 是 Context 的子类,因此可以调用 Context 中定义的方法,包括 getString() 方法。getString() 方法会根据传入的字符串资源的唯一标识符在应用程序的资源池中查找对应的字符串资源,并返回该字符串资源的值。

需要注意的是,如果我们在非 Activity 或 Fragment 的类中需要访问字符串资源,例如在 Service 或 BroadcastReceiver 中,我们需要将当前的 Context 传递给这些类,以便这些类可以访问应用程序的资源池。

上一篇 下一篇