Android开发常见错误

  我们在平时Android开发的过程中,肯定会遇到各种各样的编译问题,有时候确实是我们的代码有问题;但有时候却是我们得AS配置有问题,因此本篇文章将用来一步一步的记录我在工作和学习中遇到相关的配置的问题。

1.Instant Run 导致

  当安装了新版本的AS,或者新开项目,你在编译的过程中可能会突然报以下错误信息:


image.png

解决办法就是AS的配置问题:
Android Stuido->Preferences->搜索栏搜索“Instant Run”->关闭Instant Run
就可以解决这个问题。

解释下Instant Run
Instant Run开启会加快编译,这就是它开启的作用。

  传统情况下,我们修改程序后重新运行一次程序需要经历 代码重新编译 -> 停止程序 -> 重新安装 -> 重新启动 这样一个过程,而Instant Run则尝试只将程序变更的部分部署到手机上,尽量避免重新安装或重新启动程序,以此大大提升调试程序的效率。
可以看到,运行的三角形旁边多了一个闪电符号,这就说明现在可以使用Instant Run了。


image.png

  但是随着项目的运行,发现了一个特别恶心的事,apk卸载之后,重新运行,速度会特别慢,之后就不会出现了,到今天,运行一次要10s左右,实在是受不了了,最后发现问题还是出现在Instant Run上,把Instant Run关闭了之后,再把apk卸载了,运行速度马上就正常了,2s左右吧,今天把这个记录下来,未免之后再次碰到这个问题。

2.Mac Os 升级 导致 git 命令失效

有时候手残进行了Mac Os 升级之后,你会遇到各种奇怪的问题,然后题主昨晚就进行了Os升级,升级之后,再次进行AS进行git 操作的时候,奇怪的事情就出现了,居然出现如下错误信息:

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

很是纳闷,没修改啥关于CommandLineTools的东西啊。然后各方了解了一下:
大致是OS升级后,对应的CommandLineTools并没有伴随下载。

解决办法

在命令行中执行 xcode-select --install ,然后会启动下载并安装Command line tools OS) for Xcode,注意,这个命令并不会下载完整的Xcode,但是下载依然会很慢,如果你有苹果开发者账号的话,你可以去http://developer.apple.com/downloads
然后根据提示进行安装相应的东西,就可以完美解决了。

3.InputMethodManager导致crash

我们在关于与软键盘弹出弹入的界面的时候,肯定想增强其弹出弹入的自然性,关于软键盘弹出这里不做介绍,只介绍关于关闭软键盘的crash情况。
在做关闭软键盘的操作,我们自然的写法必然如下:

((InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
                InputMethodManager.HIDE_NOT_ALWAYS);
        getActivity().supportFinishAfterTransition();

一般这样是没有问题的,但是有时候也会有crash的情况出现,比如公司的项目就出现了这样的情况,log如下:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.IBinder android.view.View.getWindowToken()' on a null object reference
at com.sankuai.movie.movie.search.SearchBaseFragment.f(MovieFile:242)
at com.sankuai.movie.movie.search.SearchBaseFragment.onClick(MovieFile:195)
at android.view.View.performClick(View.java:6306)
at android.view.ViewPerformClick.run(View.java:24813) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6747) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInitMethodAndArgsCaller.run(RuntimeInit.java:455)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
哇,是不是挺可怕的,突然就来一个crash,让人摸不着头脑,还是空指针异常,按照常理来说,这个操作不会报空指针吧,我来解释下原因吧,引用官方文档对hideSoftInputFromWindow的介绍我们似乎就可以找到原因:

public boolean hideSoftInputFromWindow(IBinder windowToken,int flags)

Synonym for `[hideSoftInputFromWindow(IBinder, int, ResultReceiver)]without a result: request to hide the soft input window from the context of the window that is currently accepting input.

windowToken:IBinder: The token of the window that is making the request, as returned by View.getWindowToken().
大概意思就是指谁触发出软键盘,在隐藏软键盘的时候,由触发出的隐藏

这下知道为什么会crash了吧,就是我们在页面弹出软键盘的时候,不一定是由Activity的全局View触发,但也不排除由全局view触发,但是我们隐藏软键盘的时候,指定view中的特定view进行隐藏就会避免不必要的crash产生。
将上面的会产生crash的代码改成如下:

((InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(etSearch.getWindowToken(),
                InputMethodManager.HIDE_NOT_ALWAYS);

便可解决此问题。

4.如何做浮点数的比较

做业务开发中,无非就是各种判断条件,但是对于整数,字符串等的比较是可以正常进行的,如果我们遇到浮点数的时候应该怎么进行尼。有的同学可能马上就要说我们可以将浮点数类型转换为String进行比较,但是你有没有想,我们要比较的是不定的浮点数,也就是可能通过大量计算的计算式,我们无法知道其精度为多少。
那么显然“==”“!=”是不能用了,那么就会有人提出来使用equals,下面给你看一个劲爆的例子:

Double a = Double.valueOf("0.0");  
Double b = Double.valueOf("-0.0");  
System.out.println(a.equals(b));  

结果居然是false,惊喜不,别着急还有更惊喜的:

 public static void main(String[] args) {
        Double a = Math.sqrt(-1.0);
        Double b = 0.0d / 0.0d;
        Double c = a + 1.0d;
        Double d = b + 2.0d;
        System.out.println(a.equals(b));
        System.out.println(b.equals(c));
        System.out.println(c.equals(d));
}

它会丧心病狂的全部返回为true.
在java里,a和b都属于NaN,因此便无法进行比较操作了;对于equals方法,是比较2个对象是否等值,而不是对象的值是否相等,所以equals方法设计的初衷根本就不是用来做数值比较的,因此我们不能想当然的认为equals是万能的.

接下来又会有同学进行反驳说,可以使用compareTo;
虽然说它在设计上是用于数值比较的,但它表现跟equals方法一模一样(对于NaN和0.0与-0.0),但是我们在进行浮点数比较的时候,一般是至少有一方是经过表达式计算返回的值,我们必定会存在舍入误差,因此也不建议直接使用Float.compareTo和Double.compareTo方法.

通过上面的分析,针对的给出解决方案就是,避免NaN,然后化无穷为有穷,给定精度值,进行比较
类似的给出float和double的封装方法参考:

//精度值
private static final double EPSILON = 0.000001;
 /**
     * 比较两个浮点数是否相等
     * @param f1
     * @param f2
     * @return
     */
public static boolean isEquals(float f1,float f2) {
      if (Math.abs(f1 - f2) < EPSILON) {
          return true;
      } else {
          return false;
      }
}
 /**
     * 比较两个浮点数是否相等
     * @param d1
     * @param d2
     * @return
     */
public static boolean isEquals(double d1,double d2) {
      if (Math.abs(d1 - d2) < EPSILON) {
          return true;
      } else {
          return false;
     }
}

你可能感兴趣的:(Android开发常见错误)