Android常见问题及答案收集

android 常见问题及答案收集。
不断收集中


同一个Activity怎么动态添加删除多层View(多套xml)

  • setContentView(@LayoutRes int layoutResID); 替换当前activity的布局
  • addContentView(View view, ViewGroup.LayoutParams params); 添加View到当前activity的上层
  • 移除addContentView的View
    1
    2
    3
    4
    // 假设 frameLayout 就是添加的View
    if (frameLayout != null && frameLayout.getParent() != null && frameLayout instanceof ViewGroup) {
    ((ViewGroup) frameLayout.getParent()).removeView(frameLayout);
    }

Android 中的数据存储有哪些

  • Shared Preferences
  • 内部存储
  • 外部存储
  • 本地数据库存储
  • 通过网络在服务器端数据库存储

请解释什么是进程(Process)与线程(Thread)

  • 进程是操作系统结构的基础,是计算机中正在运行的程序实例,它可以被分配给处理机并被处理机执行。通俗地说,就是一个正在运行的应用程序实体。
  • 线程是进程中某个单一顺序的控制流,它也被称为轻量级进程(Lightweight Process),它是处理机调度的基本单位。

请分析说明进程与线程的四点区别

  • 地址空间和数据资源:进程间相互独立;同一进程的各线程间共享,但某进程内的线程在其它进程不可见。
  • 通信:进程间通信需要专门的机制;线程间可以直接读写全局变量来进行通信,不过需要同步和互斥手段的辅助,以保证数据的一致性
  • 调度和切换:线程上下文切换比进程上下文切换要快得多。
  • 在多线程OS中,进程不是一个可执行的实体。

android中线程与线程,进程与进程之间如何通信

  • 一个 Android 程序开始运行时,会单独启动一个Process。 默认情况下,所有这个程序中的Activity或者Service都会跑在这个Process。默认情况下,一个Android程序也只有一个Process,但一个Process下却可以有许多个Thread。
  • 一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。
  • 一个Android程序创建之初,一个Process呈现的是单线程模型–即Main Thread,所有的任务都在一个线程中运行。所以,Main Thread所调用的每一个函数,其耗时应该越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象)。
  • Android单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。如果在子线程中直接修改UI,会导致异常。

请一一简述Android中的五类进程

  • 前台进程(Foreground process):用来处理用户正在进行的工作的进程。
  • 可见进程( Visible process):这种进程并不包含任何前台组件,但是包含仍然被用户可见的组件。
  • 服务进程(Service process):其中运行着使用startService()方法启动的Service,并且没有变为更高的两个级别的进程。
  • 后台进程(Background process):处理后台事务的进程,比如其中运行着执行了onStop()方法而处于停止态的Activity等
  • 空进程(Empty process):不包含任何活动的应用程序组件的进程。

GET和POST方法主要的三点区别

  • POST请求可以向服务器传送数据,而且数据放在HTML HEADER内一起传送到服务端URL地址,数据对用户不可见。而GET是把参数数据队列加到提交的URL中,值和表单内各个字段一一对应。
  • GET传送的数据量较小,不能大于2KB。POST传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
  • GET安全性非常低,POST安全性较高

Object有哪些公用方法

  • equals 判断两个对象是否相等
  • clone 进行对象拷贝
  • getClass 返回和当前对象相关的Class对象
  • notify,notifyall,wait都是用来对给定对象进行线程同步的

Java中try catch finally的执行顺序

先执行try,如果发生异常执行catch,最后一定会执行finally

equals与==的区别

  • ==是判断两个变量或实例是不是指向同一个内存空间
  • equals是判断两个变量或实例所指向的内存空间的值是不是相同

String、StringBuffer与StringBuilder的区别

  • String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象
  • StringBuffer和StringBuilder底层是 char[]数组实现的
  • StringBuffer是线程安全的,而StringBuilder是线程不安全的

Java的四种引用的区别

  • 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM 也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象
  • 软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收
  • 弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象
  • 虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收

垃圾回收机制

  • 标记回收法:遍历对象图并且记录可到达的对象,以便删除不可到达的对象,一般使用单线程工作并且可能产生内存碎片
  • 标记-压缩回收法:前期与第一种方法相同,只是多了一步,将所有的存活对象压缩到内存的一端,这样内存碎片就可以合成一大块可再利用的内存区域,提高了内存利用率
  • 复制回收法:把现有内存空间分成两部分,gc运行时,它把可到达对象复制到另一半空间,再清空正在使用的空间的全部对象。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。
  • 分代回收发:把内存空间分为两个或者多个域,如年轻代和老年代,年轻代的特点是对象会很快被回收,因此在年轻代使用效率比较高的算法。当一个对象经过几次回收后依然存活,对象就会被放入称为老年的内存空间,老年代则采取标记-压缩算法

handler机制的原理

andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)

  • Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)
  • Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息
  • Message Queue(消息队列):用来存放线程放入的消息
  • 线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue

对于同一个Service,在被start启动之后还能不能被bind

静态内部类、内部类、匿名内部类,为什么内部类会持有外部类的引用?持有的引用是this?还是其它

  • 静态内部类:使用static修饰的内部类
  • 内部类:就是在某个类的内部又定义了一个类,内部类所嵌入的类称为外部类
  • 匿名内部类:使用new生成的内部类
  • 因为内部类的产生依赖于外部类,持有的引用是类名.this

请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系

  • Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。
  • Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,并且只能处理该消息队列中的消息。
  • Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的。
  • Handler,Handler接受到消息后调用handleMessage进行处理。
  • Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理。

如何避免Android 弹出键盘往上挤压页面

  • 在Activity里面加入android:windowsoftinputmode=”adjustPan”代码,这样键盘就会覆盖屏幕。
  • 如果不想键盘覆盖屏幕,想让屏幕整体上移,就加入属性android:windowsoftinputmode=”statevisible|adjustresize
  • 相关属性介绍

android.content.res.Resources$NotFoundException 异常可能情况有哪些

  • UncaughtException detected: android.content.res.Resources$NotFoundException: Resource ID #0xffffffff
    • 该情况最有可能是 ImageView.setImageResource(-1) (#0xffffffff 存储值等于 -1)
  • 其他不存在的Id赋值导致
    • 多检查资源文件是否R文件中

有什么黑科技可以一劳永逸清除滥用log

  • 如下,在release中的Proguard文件中添加以下代码,参考黑科技:用Proguard的-assumenosideeffects清除log
    1
    2
    3
    4
    5
    6
    7
    8
    9
    -assumenosideeffects class android.util.Log {   
    public static *** d(...);
    public static *** e(...);
    public static *** i(...);
    public static *** v(...);
    public static *** println(...);
    public static *** w(...);
    public static *** wtf(...);
    }

webview加载网页出现(“找不到网页net:err_unknown_url_scheme”)

  • 由于Webview只能识别http、https开头的网页,导致如果打开不是这两个开头的网址会出现:加载网页出现(“找不到网页net:err_unknown_url_scheme”)的错误。

  • 解决方案如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url)
    {
    if(url == null) return false;

    try {
    if (url.startsWith("http:") || url.startsWith("https:"))
    {
    view.loadUrl(url);
    return true;
    }
    else
    {
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    startActivity(intent);
    return true;
    }
    } catch (Exception e) { //防止crash (如果手机上没有安装处理某个scheme开头的url的APP, 会导致crash)
    return false;
    }
    }
    });

    Java去掉小数点后面不需要的0

  • 方法1

    1
    2
    3
    4
    5
    6
    String s = "111.01100";
    if(s.indexOf(".") > 0){
      //正则表达
      s = s.replaceAll("0+?$", "");//去掉后面无用的零
      s = s.replaceAll("[.]$", "");//如小数点后面全是零则去掉小数点
    }
  • 方法2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     /**
    * 去掉小数点后多余的0,
    *
    * @param ruleReduce
    * @return
    */
    public static String strToDouble(String ruleReduce) {
    //去掉多余的小数点
    if (ruleReduce != null && ruleReduce.indexOf( "." ) > 0) {
    //正则表达
    //去掉后面无用的零
    ruleReduce = ruleReduce.replaceAll( "0+?$", "" );
    //如小数点后面全是零则去掉小数点
    ruleReduce = ruleReduce.replaceAll( "[.]$", "" );
    }
    return ruleReduce;
    }

RecyclerView 与 ScrollView嵌套滑动

~~java
recyclerView.setNestedScrollingEnabled(false);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

## Android Studio提示“Cause: jcenter.bintray.com:443 failed to respond”解决

由于Android Studio有的依赖包国内访问不了,设置不了代理,后来在Android Studio 3.1,一直提示“Cause: jcenter.bintray.com:443 failed to respond”,后来搜索到网上说可能是代理的原因,在“C:\Users\Administrator\.gradle\gradle.properties",把systemProp.https.proxyPort和systemProp.https.proxyHost的代理注销了,就正常了。能正常运行的gradle.properties如下:

~~~java
# org.gradle.parallel=true

#Fri Jun 29 10:45:08 CST 2018

#systemProp.https.proxyPort=1080

systemProp.http.proxyHost=127.0.0.1
#systemProp.https.proxyHost=127.0.0.1
systemProp.http.proxyPort=1080

Fragment null must be a public static class to be properly recreated from instance state.

问题原因:

1
Fragment不能写成抽象的,直接new的方式绑定在Activity上

解决方案:

1
2
方式1: 写子类实现抽象方法,再绑定在Activity
方式2: 不写成抽象类,子类new之后,已属性的方式设置代理方法进去

解决 java double 加减乘除带来的精度丢失问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* double两数相减
* @param num1
* @param num2
* @return
*/
public static double subtract(String num1, String num2) {
BigDecimal b1 = new BigDecimal( num1 );
BigDecimal b2 = new BigDecimal( num2 );
return b1.subtract( b2 ).doubleValue();
}
/**
* 加法
* @param num1
* @param num2
* @return
*/
public static double add(String num1, String num2) {
BigDecimal b1 = new BigDecimal( num1 );
BigDecimal b2 = new BigDecimal( num2 );
return b1.add( b2 ).doubleValue();
}
/**
* 乘法
* @param num1
* @param num2
* @return
*/
public static double multiply(String num1, String num2) {
BigDecimal b1 = new BigDecimal( num1 );
BigDecimal b2 = new BigDecimal( num2 );
return b1.multiply( b2 ).doubleValue();

}
/**
* 除法
* @param num1
* @param num2
* @return
*/
public static double divide(String num1, String num2) {
BigDecimal b1 = new BigDecimal( num1 );
BigDecimal b2 = new BigDecimal( num2 );
return b1.divide( b2 ).doubleValue();
}

其他相关推荐

android 相关规范