问题描述
下面的代码在Kotlin/Android中崩溃,底部提供了堆栈跟踪.它是从Java/Android转换而来的,它没有这样的问题.还提供了原始Java代码.当我尝试将字符添加到密码字段时,发生崩溃.编辑现有字符效果很好.
The code below crashes in Kotlin/Android with the stack trace provided on the bottom. It was converted from Java/Android, which didn't have such a problem. Original Java code is provided as well. The crash happens when I try to add a character to a password field. Editing existing characters works well.
对此我有两个问题:
- Kotlin用Kotlin的CharSequence替换java.lang.CharSequence的动机是什么?这两个是完全不同的,我怀疑这会导致崩溃.
- 有什么办法可以使其在Kotlin中工作?
科特琳代码使Android的Paint崩溃
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的字符时发生崩溃.从未添加过它,也没有出现在
10 is a CharSequence length here. First digit - current index. Crash happens when I was trying to add a char with index 9 from a keyboard. It was never added and didn't show up in the output below
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文件.我用它来解决问题.
Fortunately, Android/Kotlin allows mixing Java and Kotlin files in a single project. I used this as a work around for the problem.
创建了一个用于处理密码的Java类.请注意,CharSequence在这里是本机Java类,这有所作为.
Created a Java class for the password handling. Please notice, CharSequence is a native Java class here, and this makes a difference.
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的解决方案.
Instantiated this class in getTransfromation method in a Kotlin's class. Kotlin compiler took it well this time. Crashes do not happen anymore.I still would like to see a pure Kotlin's solution for this.
mPwd!!.transformationMethod = object : PasswordTransformationMethod() {
override fun getTransformation(source: CharSequence, view: View): CharSequence {
return PasswordHandler(source, mChkUnmask)
}
}
这篇关于Java正常运行时,Kotlin在PasswordTransformationMethod中崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!