Kotlin 在 PasswordTransformationMethod 中崩溃,而 Java 工作正常

2024-01-26

下面的代码在 Kotlin/Android 中崩溃,堆栈跟踪位于底部。它是从Java/Android转换而来的,没有这样的问题。还提供了原始 Java 代码。当我尝试向密码字段添加字符时发生崩溃。编辑现有字符效果很好。

我对此有两个问题:

  1. Kotlin 用 Kotlin 的 CharSequence 替换 java.lang.CharSequence 的动机是什么?这两者有很大不同,我怀疑它导致了崩溃。
  2. 有什么办法让它在 Kotlin 中工作吗?

导致 Android Paint 崩溃的 Kotlin 代码

        mPwd!!.transformationMethod = object : PasswordTransformationMethod() {
        override fun getTransformation(source: CharSequence, view: View): CharSequence {
            return PasswordCharSequence(source)
        }
        internal inner class PasswordCharSequence(private val source: CharSequence)// Store char sequence
            : CharSequence {

            val mSource = source
            public override val length = mSource.length

            init {
                App.d(TAG, "SOURCE " + mSource + " " + length)
            }
            override fun get(index: Int): Char {
                App.d(TAG, "SOURCE IND " + index + " " + mSource.length)
                return if (mChkUnmask!!.isChecked) mSource.get(index) else '*'
            }
            override fun subSequence(start: Int, end: Int): CharSequence {
                App.d(TAG, "SOURCE SUB " + start + " " + end)
                return mSource.subSequence(start, end) // Return default
            }
        }
    }

运行良好的原始 Java 代码

        mPwd.setTransformationMethod(new PasswordTransformationMethod() {

        @Override
        public CharSequence getTransformation(CharSequence source, View view) {
            return new PasswordCharSequence(source);
        }

        class PasswordCharSequence implements CharSequence {
            private CharSequence mSource;
            public PasswordCharSequence(CharSequence source) {
                mSource = source; // Store char sequence
            }
            public char charAt(int index) {
                return mChkUnmask.isChecked()?mSource.charAt(index):'*';
            }
            public int length() {
                return mSource.length(); // Return default
            }
            public CharSequence subSequence(int start, int end) {
                return mSource.subSequence(start, end); // Return default
            }
        }
    });

来自 Logcat 的堆栈跟踪

06-03 00:35:08.143 16694 16694 E AndroidRuntime: java.lang.IndexOutOfBoundsException
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.graphics.Paint.getRunAdvance(Paint.java:2986)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.handleText(TextLine.java:719)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.handleRun(TextLine.java:873)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.measureRun(TextLine.java:387)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.measure(TextLine.java:277)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.TextLine.metrics(TextLine.java:251)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.Layout.getLineExtent(Layout.java:1072)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.text.Layout.getLineWidth(Layout.java:1038)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.TextView.desired(TextView.java:8142)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.TextView.onMeasure(TextView.java:8208)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6459)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.View.measure(View.java:21051)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6459)
06-03 00:35:08.143 16694 16694 E AndroidRuntime:        at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:400)

Log.d(...) 的程序输出

10 是这里的 CharSequence 长度。第一个数字 - 当前索引。当我尝试从键盘添加索引为 9 的字符时发生崩溃。它从未被添加,也没有出现在下面的输出中

06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 810
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 710
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 610
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 510
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 410
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 310
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 210
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 110
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 010
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 010
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 110
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 210
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 310
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 410
06-03 00:35:08.121 16694 16694 D GAC-STORE: SOURCE IND 510
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 610
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 710
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 810
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 010
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 110
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 210
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 310
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 410
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 510
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 610
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 710
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 810
06-03 00:35:08.122 16694 16694 D GAC-STORE: SOURCE IND 810

mPwd 的布局

<EditText
    android:id="@+id/txtDlgPwd"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/chkStorePwd"
    android:hint ="Ecnryption Password"
    android:maxLines="1"
    android:singleLine="true"
    android:inputType="textPassword|textNoSuggestions"
    android:imeOptions="actionDone"
    android:layout_marginLeft="10dp"
    android:layout_marginTop="20dp"
    android:textSize="15sp"/>

幸运的是,Android/Kotlin 允许在单个项目中混合 Java 和 Kotlin 文件。我用它来解决这个问题。

创建了一个用于密码处理的 Java 类。请注意,CharSequence 是这里的原生 Java 类,这会产生影响。

import java.lang.CharSequence;

public class PasswordHandler implements CharSequence {

    private CharSequence mSource;
    private Switch mUnmask;

    public PasswordHandler(CharSequence source, Switch unmask) {
        mSource = source;
        mUnmask = unmask;
    }

    public char charAt(int index) {
        return mUnmask.isChecked()?mSource.charAt(index):'*';
    }
    public int length() {
        return mSource.length();
    }
    public CharSequence subSequence(int start, int end) {
        return mSource.subSequence(start, end);
    }

    @NonNull
    @Override
    public String toString() {
        String star = new String();
        int l = length();
        if (!mUnmask.isChecked()) {
            while (l-- > 0){
                star += "*";
            }
        }
        return mUnmask.isChecked()? mSource.toString():star;
    }
}

在 Kotlin 类的 getTransfromation 方法中实例化此类。 Kotlin 编译器这次做得很好。崩溃不再发生。我仍然希望看到一个纯 Kotlin 的解决方案。

mPwd!!.transformationMethod = object : PasswordTransformationMethod() {
            override fun getTransformation(source: CharSequence, view: View): CharSequence {
                return PasswordHandler(source, mChkUnmask)
            }

        } 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kotlin 在 PasswordTransformationMethod 中崩溃,而 Java 工作正常 的相关文章

  • Android 的@hide 注解到底有什么作用?

    Android中很多内部API都被标记出来了 hide What exactly这是吗 另一个答案 https stackoverflow com questions 17035271 what does hide mean in the
  • 从 java 活动 *.java 启动 kotlin 活动 *.kt?

    使缓存无效 重新启动 帮助我 我在java类中的代码是 Intent intent new Intent view getActivity AddPaymentActivity class view getActivity startAct
  • 使用协程对任务进行排队

    我最近开始阅读有关协程的内容 我想询问某个场景 考虑一个带有一个按钮的简单屏幕 单击后 它会执行一堆打印语句和一些延迟 其间 到目前为止 我正在使用协程来实现这一目标 现在 我的问题是 如果用户反复向该按钮发送垃圾邮件 是否有一种方法可以将
  • Kotlin 中 with 和 run 的区别

    Do with and run具有相同的功能 只是语法不同 或者之间是否存在重大差异with and run 哪个是正确的方法 adapter run notifyDataSetChanged if activityDetails isEm
  • 错误包括 bouncycastle 提供商

    我需要使用bouncycastle provider我的项目中的库 我已将其包含在 gradle 项目中 apply plugin application sourceCompatibility 1 6 version 1 0 0 main
  • Keytool 不要求别名密码

    我正在尝试生成一个密钥库文件来签署我的 React Native Android 应用程序并将其发布到 Play 商店 我正在尝试按照本文档中的描述进行操作 https facebook github io react native doc
  • 将 glReadPixels 替换为 EGL_KHR_image_base 以加快像素复制速度

    我试图在 Android 本机进程中使用 EGL KHR image base 来替换 glReadPixels 因为它很慢 1280x800 RGBA 为 220ms 这是我到目前为止所拥有的 但我的它产生一个空缓冲区 只有零 uint8
  • Android 中 Bitmap 和 Drawable 有什么区别?

    我用谷歌搜索 但找不到任何文章来描述 Android 中 Bitmap 和 Drawable 之间的区别 位图是位图图像的表示 类似于 java awt Image Drawable 是 可以绘制的东西 的抽象 它可能是一个位图 包装为Bi
  • 使用 Kotlin 查找数组中最后一次出现的字符串

    我有这个数组 cat dog lion tiger dog rabbit 我怎样才能找到position of the first dog 我怎样才能找到position of last dog 我怎样才能扔一个error当我搜索不在数组中
  • 如何在列表视图中选择时启用视频序列自动播放?

    大家好 有人可以与我分享一下我如何编写我的 viewvideo java 类 以便它允许自动播放视频功能 自动排序在列表视图中播放所选视频的任务 从当前位置到最新录制的视频 按顺序直到最新的视频播放完毕 这类似于 YouTube 自动播放功
  • jasper 报告文件中出现错误

    首先 我在 iReport 5 1 0 中创建一个 R D1 jrxml 文件 我执行该报告的 Java 代码如下所示 import java sql Connection import java sql DriverManager imp
  • 使用 Google 语音服务查询支持的语言不适用于 Android 13

    我使用以下命令查询语音服务支持的语言RecognizerIntent ACTION GET LANGUAGE DETAILS action val intent Intent RecognizerIntent ACTION GET LANG
  • 从另一个活动返回时 Android ListView 项目没有响应?

    我从 ArrayAdapter 创建一个 ListView ListView的每一行都有一个ImageView和一个TextView 现在我使用 setOnItemClickListener 处理单击事件 lv getListView lv
  • java.lang.IllegalStateException:FragmentManager 已被销毁

    活动中onResume我称之为 volley request 的方法 它获取项目列表 然后将它们加载到此活动内的 ListFragment 中 当我第一次进入活动时 一切正常 但当我重新进入活动时 ListFragment 为空 并且控制台
  • 我可以像 justify 这样设置 Textview 的属性吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想设置 TextView 属性 如右对齐 左对齐 对齐 不 你不能设置像重力这样的属性 但您仍然可以通过采用 web 视图而不是文本视图
  • Android动态功能模块,找不到资源

    当下载的功能模块发布到 Play 商店时 我在启动活动时遇到问题 它总是在下载模块活动中的 setContentView 上崩溃 java lang RuntimeException Unable to start activity Com
  • 使用 ProcessBuilder 启动 CMD

    我尝试使用以下代码在 Windows 中启动 CMD 应用程序 但它无法按预期工作 来自不同网站的几个示例表明 cmd 作为 ProcessBuilder 构造中的参数应该有效 我需要做什么才能让我的 Java 应用程序在 Windows
  • 访问手机内部存储以推送 SQLite 数据库文件

    我正在使用 Netbeans 和 java 开发我的 Android 应用程序 当我使用模拟器时 我可以访问文件资源管理器并通过访问以下路径将 SQLite 数据库插入到设备内存中 data data com example helloan
  • 不鼓励在Web应用程序中使用线程吗?

    我们与同事就在 Java 的 Web 应用程序中使用线程进行了激烈的讨论 他们的观点是 不建议在 Java Web 应用程序中使用线程 因为它们不受容器管理 一般来说 我对此表示同意 因为线程可能会干扰容器 但是 如果它不是 Java EE
  • 片段已添加 IllegalStateException

    我在容器 Activity 上使用此方法来显示 BFrag public void showBFrag Start a new FragmentTransaction FragmentTransaction fragmentTransact

随机推荐