问题描述
某牙刷安卓程序在输入框中输入数字位数超过 10 位后,程序会闪退,问题是必现的,多个输入框都有相同的问题。
由于我从来没有写过安卓程序,只能勉为其难的搞一下。
定位过程
从 xml 文件找起
使用输入框的名称——舵机,在源码中搜索,搜索到的 xml 文件中有下面这些代码:
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="57dp"
android:text="舵机1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/start_btn"
tools:ignore="MissingConstraints" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.49878347" />
<EditText
android:id="@+id/sg_1_et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:ems="3"
android:gravity="center"
android:inputType="number"
android:lines="1"
app:layout_constraintBottom_toBottomOf="@+id/textView2"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toEndOf="@+id/textView2"
app:layout_constraintTop_toTopOf="@+id/textView2"
tools:ignore="MissingConstraints" />
根据我之前开发 gui 程序的经验,这个 xml 描述了页面的布局,其中重要的部分是每一个控件的 id,layout 的内容只与显示有关,与我们这里的问题毫不相关。
可以看到对应舵机 1 的输入框,其控件 id 是 “@+id/sg_1_et”,这个名称看上去多少有点奇怪,@+id/ 应该是有特定的作用,真正的名字应该是 sg_1_et。
使用输入框 id 搜索代码
使用 sg_1_et 为关键词,在源码中搜索,找到了相关文件后阅读源码,看到了如下内容:
public void afterTextChanged(Editable s) {
这个函数应该是输入框内容改变后调用的事件函数,s 表示一个输入框对象,从这个对象上能够获取到输入框的内容。
解析输入框内容的代码如下:
orderClass.cmdvalue = getData(0,Integer.parseInt(s.toString()),10,0)+"";
getData 是本地定义的一个函数,其原型如下:
public int getData(int id, int angle, int seep, int isWait) {
可以确定 getData 不会出现异常崩溃的问题,它可能的问题是计算结果不准确。那么看来问题只能出在 Integer.parseInt 上了。
Integer.parseInt 方法存在的问题
网上搜索了下这个方法,获取到了如下信息:
parseInt() 方法用于将字符串参数作为有符号的十进制整数进行解析
我使用如下 demo 进行测试,此 demo 摘自 Java parseInt() 方法 这个网页中。
public class Test{
public static void main(String args[]){
int x =Integer.parseInt("9");
double c = Double.parseDouble("5");
int b = Integer.parseInt("444",16);
System.out.println(x);
System.out.println(c);
System.out.println(b);
}
}
修改 parseInt 的参数为一个超过 10 位的字符串,然后将上述代码保存为 Test.java,执行 java Test.java 运行后,程序抛出了如下异常信息:
Exception in thread "main" java.lang.NumberFormatException: For input string: "12345678901111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Test.main(Test.java:3)
我修改的内容是 “12345678901”,模拟了上面描述的输入超过 10 位数字的行为,果然复现了相同的问题,看来问题就在这里了。
如何修改?
根据上面的信息,应该是输入的数字超过了 int 型的范围导致的问题。继续网上搜索,发现可以使用大数类——BigInteger 来解决这个问题。
一个具体的使用 demo 如下:
import java.math.BigInteger;
public class Test{
public static void main(String args[]){
BigInteger x = new BigInteger("123456789");
int value = x.intValue();
System.out.println(value);
}
}
这个 demo 的内容正说明了问题的解决方案,其它的细节不再描述。
总结
我从来没有开发过安卓程序,这是一个事实,但它并不代表我不能解决这里遇到的问题。
定位这个问题的思路与定位其它完全不同类型问题的思路其实也是类似的,不同的问题在某些形式上可能有很大的差别,可是真正基础的东西却可能是一致的。