(转载)Android+Java知识点总结

来源:互联网 发布:网站编辑seo是什么 编辑:程序博客网 时间:2024/06/08 19:23

本文系原创,如需转载请联系作者并请注明出处:http://blog.csdn.net/woshizisezise/article/details/52403692

前言:大家好,最近不管是看书也好,看博客也好,看到许多自己曾经看过但是可能时间久了有点记得不太清的内容,于是乎就想以后要是这种情况,现在何不随手记录下来呢,方便自己以后阅读回顾,同时也可以给大家提供帮助,所以在很长的一段时间内,我都会简短但是清楚的说明一个知识点,考虑到如果每个知识点都写的非常详细的话,篇幅会很长,并且查找起来也非常费力,所以如果有关的重点,我会单独的抽取出来详细讲解,本篇博客只为重点,谢谢大家!

知识点1
从activityA打开跳转到activityB,生命周期先执行的是activityA的onPause()方法,然后才走的activityB的onCreate()、onStart()、onResume()方法,最后才走的activityA的onStop()、onDestroy()方法;

知识点2. 
如果为一个activity设置了launchMode为SingleTask模式的话,重复启动它并不会每次执行onCreate()方法(第一次除外),但是会每次执行onPause()、onNewIntent()、onResume()方法;

知识点3 
线程和进程的区别是什么? 
线程:CPU调度的最小单元,是一种有限的系统资源; 
进程:一般指一个执行单元,在PC和移动设备上指一个程序或一个应用;

进程和线程是包含与被包含的关系,一个进程中可以有一个线程(主线程)也可以有多个线程(多线程);

知识点4 
在Android中开启多进程只有一种方法,那就是给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidManifest.xml中指定android:process属性;

知识点5 
使用多进程可能会造成以下问题: 
1.静态成员和单例模式完全失效; 
2.线程同步完全失效; 
3.SharedPreferences可靠性下降; 
4.Application会多次创建;

知识点6 
Serializable和Parcelable的区别: 
Serializable:是java中的序列化接口,使用简单但是开销大; 
Parcelable:是Android中的序列化方式,虽然使用起来麻烦一点,但是效率很高;

因此我们首选Parcelable方式实现序列化;

知识点7 
RelativeLayout和LinearLayout绘制问题: 
RelativeLayout绘制时间比LinearLayout绘制时间稍长,因为RelativeLayout会进行两次的绘制工作,一次横向,一次纵向,而LinearLayout在没有设置weight属性的情况下只进行一次绘制,只有当设置了weight属性的情况下才会进行两次绘制,所以在绘制时间上,LinearLayout稍快。

知识点8 
static只能用来修饰成员变量,不能修饰局部变量,编译时会报错,例如下列代码会报错:

public class Student{    public void study(){        static int num = 10;    }}
  • 1
  • 2
  • 3
  • 4
  • 5

知识点9 
java中四种访问控制级别: 
1.private(类访问级别):如果类的成员被private访问控制符修饰,则这个成员只能被该类的其它成员访问,其他类无法直接访问。类的良好封装性就是通过private关键字来实现的。 
2.default(包访问级别):如果一个类或者类的成员不使用任何访问控制修饰符,则称它为默认访问控制级别,这个类或者类的成员只能被本包中的其他类访问。 
3.protected(子类访问级别):如果一个类的成员被protected访问控制符修饰,那么这个成员既能被同一包下的其他类访问,也能被不同包下该类的子类访问。 
4.public(公共访问级别):这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中。

访问范围privatedefaultprotectedpublic同一类中☑️☑️☑️☑️同一包中 ☑️☑️☑️子类中  ☑️☑️全局范围   ☑️

知识点10 
Collection有两个重要的子接口,分别是List和Set,其中List的特点是元素有序,元素可重复。Set的特点是元素无序且不可重复。List接口的主要实现类有ArrayList和LinkedList,Set接口的主要实现类有HashSet和TreeSet。

知识点11 
由于ArrayList集合的底层是使用一个数组来保存元素,在增加或删除指定位置的元素时,会导致创建新的数组,效率比较低,因此不适合做大量的增删操作。但是这种数组的结构允许程序通过索引的方式来访问元素,因此使用ArrayList集合查找元素和便捷。

知识点12 
LinkedList集合内部维护了一个双向循环列表,链表中的每一个元素都使用引用的方式来记住它的前一个元素和后一个元素,从而可以将所有的元素彼此链接起来。当插入一个新元素时,只需要修改元素之间的这种引用关系即可,删除一个节点也是如此。正因为这样的存储结构,所以LinkedList集合对于元素的增删操作具有很高的效率。

知识点13 
常见的内存泄漏 : 
1.查询数据库没有关闭Cursor。 
2.使用BaseAdapter作为适配器时没有复用convertView。 
3.bitmap没有回收。 
4.注册对象后没有反注册,比如Broadcast Receiver等。 
5.handler问题,如果handler是非静态的,会导致Activity或者Service不被回收,所以应当注册为静态内部类,同时在onDestroy时停止线程:mThread.getLooper().quit()。 
6.Activity被静态引用,特别是缓存bitmap时,解决方法可以考虑使用Application的context代替Activity的context。 
7.View在callback中被引用,可能回调还没有结束,但是view处于引用状态,无法回收。 
8.WebView的泄露问题:在魅族上面发现webView打开再关闭就会内存泄露。目前使用的解决方法是在webview外面嵌套一层layout作为container.在Activity的onDestroy中调用container.removeAllViews()方法。 
9.Dialog导致Window泄露,如果需要在dialog依附的Activity销毁前没有调用dialog.dismiss()会导致Activity泄露 。 
10.如果还有其他的,欢迎补充!

知识点14 
安卓xml绘制虚线:

<shape xmlns:android="http://schemas.android.com/apk/res/android"        android:shape="line">       <!-- 显示一条虚线,破折线的宽度为dashWith,破折线之间的空隙的宽度为dashGap,当dashGap=0dp时,为实线 -->     <stroke android:width="1dp" android:color="#D5D5D5"                   android:dashWidth="2dp" android:dashGap="3dp" />                  <!-- 虚线的高度 -->      <size android:height="2dp" />      </shape> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

知识点15 
ExpandableListView 的子列表不能点击(禁用)要把 Adapter 的 isChildSelectable 方法返回 true。

知识点16 
什么叫垃圾回收机制? 
垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用,以免造成内存泄露。

知识点17 
java的垃圾回收有什么特点? 
JAVA语言不允许程序员直接控制内存空间的使用。内存空间的分配和回收都是由JRE负责在后台自动进行的,尤其是无用内存空间的回收操作(garbagecollection,也称垃圾回收),只能由运行环境提供的一个超级线程进行监测和控制。

知识点18 
垃圾回收器什么时候会运行? 
一般是在CPU空闲或空间不足时自动进行垃圾回收,而程序员无法精确控制垃圾回收的时机和顺序等。

知识点19 
垃圾回收器是怎样工作的? 
垃圾回收器如发现一个对象不能被任何活线程访问时,他将认为该对象符合删除条件,就将其加入回收队列,但不是立即销毁对象,何时销毁并释放内存是无法预知的。垃圾回收不能强制执行,然而Java提供了一些方法(如:System.gc()方法),允许你请求JVM执行垃圾回收,而不是要求,虚拟机会尽其所能满足请求,但是不能保证JVM从内存中删除所有不用的对象。

知识点20 
如何显示的使对象符合垃圾回收条件? 
1.空引用:当对象没有对他可到达引用时,他就符合垃圾回收的条件。也就是说如果没有对他的引用,删除对象的引用就可以达到目的,因此我们可以把引用变量设置为null,来符合垃圾回收的条件。

StringBuffer sb = new StringBuffer("hello");System.out.println(sb);sb=null;
  • 1
  • 2
  • 3

2.重新为引用变量赋值:可以通过设置引用变量引用另一个对象来解除该引用变量与一个对象间的引用关系。

StringBuffer sb1 = new StringBuffer("hello");StringBuffer sb2 = new StringBuffer("goodbye");System.out.println(sb1);sb1=sb2;//此时"hello"符合回收条件  
  • 1
  • 2
  • 3
  • 4

3.方法内创建的对象:所创建的局部变量仅在该方法的作用期间内存在。一旦该方法返回,在这个方法内创建的对象就符合垃圾收集条件。有一种明显的例外情况,就是方法的返回对象。

public static void main(String[] args) {    Date d = getDate();    System.out.println("d = " + d);}private static Date getDate() {    Date d2 = new Date();    StringBuffer now = new StringBuffer(d2.toString());    System.out.println(now);    return d2;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4.隔离引用:这种情况中,被回收的对象仍具有引用,这种情况称作隔离岛。若存在这两个实例,他们互相引用,并且这两个对象的所有其他引用都删除,其他任何线程无法访问这两个对象中的任意一个。也可以符合垃圾回收条件。

public class Island {    Island i;    public static void main(String[] args) {    Island i2 = new Island();    Island i3 = new Island();    Island i4 = new Island();    i2.i=i3;    i3.i=i4;    i4.i=i2;    i2=null;    i3=null;    i4=null;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

知识点21 
垃圾收集前进行清理——finalize()方法 java提供了一种机制,使你能够在对象刚要被垃圾回收之前运行一些代码。这段代码位于名为finalize()的方法内,所有类从Object类继承这个方法。由于不能保证垃圾回收器会删除某个对象。因此放在finalize()中的代码无法保证运行。因此建议不要重写finalize()。

知识点22 
定义字符串应该尽量使用 String str=”hello”; 的形式 ,避免使用String str = new String(“hello”); 的形式。因为要使用内容相同的字符串,不必每次都new一个String。 
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。

知识点23 
尽量避免在类的构造函数里创建、初始化大量的对象 ,防止在调用其自身类的构造器时造成不必要的内存资源浪费,尤其是大对象,JVM会突然需要大量内存,这时必然会触发GC优化系统内存环境;显示的声明数组空间,而且申请数量还极大。

知识点24 
碰到一个需求,EditText默认的hint文字大小为12sp,当有文字填写时,文字大小变为18sp,在xml文件中无法实现,只能通过下列java代码实现:

etPhone = (EditText) findViewById(R.id.msg_phone);SpannableString ss = new SpannableString("请填写已经注册的手机号码");//定义hint的值AbsoluteSizeSpan ass = new AbsoluteSizeSpan(12, true);//设置字体大小 true表示单位是spss.setSpan(ass, 0, ss.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);etPhone.setHint(new SpannedString(ss));
  • 1
  • 2
  • 3
  • 4
  • 5

知识点25 
关于Toast的优化: 
如果每次都使用Toast.makeText(context,content,Toast.LENGTH_SHORT).show();来给出吐司提示的话,当你在短时间内不断点击,停止点击后会发现吐司会停留很长的一段时间,这是因为每次点击都是重新创建了一个Toast,所以这种做法会给用户造成较差的用户体验,那么正确的做法应该如下:

public class ToastUtils {    private static Toast toast;    public static void toast(Context cxt, String str) {        if (toast == null) {            toast = Toast.makeText(cxt, str, Toast.LENGTH_SHORT);        } else {            toast.setText(str);        }        toast.show();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

知识点26 
OkHttp和Volley的有什么区别?

  • OkHttp

1.占用储存空间

使用OkHttp需要 okio.jar (80k), okhttp.jar(330k)这2个jar包,总大小差不多400k,加上自己的封装,差不多得410k。

2.功能介绍

Square 公司开源的 OkHttp 是一个专注于连接效率的 HTTP 客户端。OkHttp 提供了对 HTTP/2 和 SPDY 的支持,并提供了连接池,GZIP 压缩和 HTTP 响应缓存功能。

3.优点

支持http请求,https请求。

支持文件下载。

使用的是HttpURLConnection,不要担心android版本的变换。(至少目前是都支持的)。

支持get,post请求。

基于Http的文件上传。

加载图片。

4.缺点

比如callback回来是在线程里面, 不能刷新UI,需要我们手动处理。封装比较麻烦。

  • Volley

1.占用储存空间

使用Volley 需要Volley.jar(120k),加上自己的封装最多140k。

2.功能介绍

Volley是Goole在2013年Google I/O大会上推出了一个新的网络通信框架,它是开源的。Volley 的特点:特别适合数据量小,通信频繁的网络操作。

3.优点

非常适合进行数据量不大,但通信频繁的网络操作。

内部分装了异步线程。

支持get,post网络请求。

图片下载。

可直接在主线程调用服务端并处理返回结果。

可以取消请求,容易扩展,面向接口编程。

4.缺点

对大文件下载 Volley的表现非常糟糕。

只支持http请求。

在BasicNetwork中判断了statusCode(statusCode < 200 || statusCode > 
299),如果符合条件直

接图片加载,性能一般。

使用的是httpclient,HttpURLConnection。不过在android 
6.0不支持httpclient了,如果想支持得添加org.apache.http.legacy.jar。

  • 总结

在我们平时的项目使用volley就可以了,相对okhttp,volley非常稳定。Okhttp一般混合来用,能够胜任相对复杂的需求。如今,在AndroidStudio中,网络请求还是推荐使用Retrofit2+okhttp。

知识点27 
Toast可以通过以下方法改变显示的位置:

Toast toast = Toast.makeText(MainActivity.this,"Bottom Right",Toast.LENGTH_SHORT);toast.setGravity(Gravity.BOTTOM | Gravity.RIGHT,0,0);toast.show();
  • 1
  • 2
  • 3

知识点28 
在Android中提供了三种解析XML的方式:SAX(Simple API XML),DOM(Document Objrect Model),以及Android推荐的Pull解析方式。

SAX: 是事件驱动型XML解析的一个标准接口,简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

DOM:即对象文档模型,它是将整个XML文档载入内存(所以效率较低,不推荐使用),使用DOM API遍历XML树、检索所需的数据,每一个节点当做一个对象。

Pull:运行方式与 SAX 解析器相似。它提供了类似的事件,SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。pull是一个while循环,随时可以跳出,而sax是只要解析了,就必须解析完成。

知识点29 
try catch finally,try里有return,finally还执行么?

Condition 1: 如果try中没有异常且try中有return (执行顺序)

try —- finally — return

Condition 2: 如果try中有异常并且try中有return

try—-catch—finally— return

总之 finally 永远执行!

Condition 3: try中有异常,try-catch-finally里都没有return ,finally 之后有个return

try—-catch—finally

try中有异常以后,根据java的异常机制先执行catch后执行finally,此时错误异常已经抛出,程序因异常而终止,所以你的return是不会执行的

Condition 4: 当 try和finally中都有return时,finally中的return会覆盖掉其它位置的return(多个return会报unreachable code,编译不会通过)。

Condition 5: 当finally中不存在return,而catch中存在return,但finally中要修改catch中return 的变量值时

int ret = 0;try{     throw new Exception();}catch(Exception e){    ret = 1;  return ret;}finally{    ret = 2;} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

最后返回值是1,因为return的值在执行finally之前已经确定下来了

知识点30

不同版本的系统如何统一弹出Material Design风格?

AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("Title")       .setMessage("Dialog content.")       .setPositiveButton("OK", new DialogInterface.OnClickListener() {               @Override               public void onClick(DialogInterface dialog,                int which) {               }       })       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {               @Override               public void onClick(DialogInterface dialog,                int which) {               }        })       .show();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这段代码就可以弹出一个非常精美的Dialog了,如下图所示: 
这里写图片描述

现在这个Dialog是Material Design风格的,因为我是在6.0系统上运行的,因此会自动赋予这样的风格。但是如果在老版本系统上运行,比如说2.3系统,会是什么样的效果呢?运行一下就知道了,如下图所示: 
这里写图片描述

人的审美总是在进步的,我们有没有什么办法在老版本的系统中也使用Material Design风格的Dialog呢?当然有,Google已经充分考虑到了这一点,在appcompat-v7库中也提供了一个AlertDialog类,完整路径是:

android.support.v7.app.AlertDialog

我们使用这个包中的AlertDialog,就能让对话框在所有的系统版本中都保持一致的风格了。现在在2.3系统中重新运行一下,效果如下所示: 
这里写图片描述

可以看到,现在的效果就比较不错了,这也算是一个小技巧吧。

Dialog的作用是给用户一个提示信息,并让用户根据提示做出判断。而Dialog的特征就是,它会阻止你原本正在进行的操作,必须停止下来对Dialog进行处理。但是,大多数的人可能并不喜欢这样被打断,也许用户正在处理一项重要的操作,突然弹出一个Dialog遮挡住了他原本的操作,这个时候用户会变得很恼火。

因此,使用Dialog的时候还是谨慎一点比较好,尽量不要给用户带来糟糕的体验感。

知识点31

如果说Dialog和Toast是两个极端的话,那么Snackbar就是处于中间的位置了。Snackbar和Toast比较相似,但是用途更加广泛,并且它是可以和用户进行交互的。Snackbar使用一个动画效果从屏幕的底部弹出来,过一段时间后也会自动消失。

在使用Snackbar之前,首先需要在app/build.gradle中添加相应的依赖:

dependencies {    compile 'com.android.support:design:23.4.0'}
  • 1
  • 2
  • 3

然后就可以使用Snackbar了,它的用法和Toast是比较相似的:

Snackbar.make(view, "data deleted",Snackbar.LENGTH_LONG)        .setAction("Undo", new View.OnClickListener(){                @Override                public void onClick(View v) {                }            })        .show();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里调用Snackbar的make()方法来创建一个Snackbar对象,make()方法的第一个参数需要传入一个view,只要是当前界面布局的任意一个view都可以,Snackbar会使用这个view来自动查找最外层的布局,用于展示Snackbar。第二个参数就是Snackbar中显示的内容,第三个参数是Snackbar显示的时长。这些和Toast都是类似的。

接着这里又调用了一个setAction()方法来设置一个动作,从而让Snackbar不仅仅是一个提示,而是可以和用户进行交互的。最后调用show()方法让Snackbar显示出来。

现在重新运行一下程序,效果如下图所示: 
这里写图片描述

可以看到,Snackbar的效果有点类似于Toast,不过它是从屏幕底部弹出来的。另外Snackbar上面可以加入和用户交互的按钮,比如删除数据的时候给用户一个Undo的选项,从这些小的细节方面都可以提升很多的用户体验。

知识点32

*Dialog、Toast和Snackbar的使用总结:*

现在你有三种方式可以给用户提示信息,Dialog、Toast和Snackbar,下面我们对这三种方式的使用时机做个总结吧。

  • Dialog:当提示信息是至关重要的,并且必须要由用户做出决定才能继续的时候,使用Dialog。

  • Toast:当提示信息只是告知用户某个事情发生了,用户不需要对这个事情做出响应的时候,使用Toast。

  • Snackbar:以上两者之外的任何其他场景,Snackbar可能会是你最好的选择。

知识点33

单例模式的最佳实现:

public class SingleTest {    private SingleTest() {    }    private static volatile SingleTest instance;    public static SingleTest getInstance() {        if (instance == null) {            synchronized (SingleTest.class) {                if (instance == null) {                    instance = new SingleTest();                }            }        }        return instance;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

知识点34

在一个子线程中使用Handler的方式应该是这样的:

class LooperThread extends Thread {     public Handler mHandler;    public void run() {         Looper.prepare();         mHandler = new Handler() {             public void handleMessage(Message msg) {             }         };        Looper.loop();       }   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 为什么我们平常在MainActivity中使用Handler时并没有调用Looper.prepare()也没有报错呢?

这是因为UI线程是主线程,系统会自动调用Looper.prepareMainLooper()方法创建主线程的Looper和消息队列MessageQueue

知识点35

*使用Handler的错误姿势及其潜在风险*

1.handler.post(Runnable runnable)、view.post(Runnable runnable)、Activity.runOnUiThread(Runnable runnable)的runnable均会在主线程中执行,所以切勿在其run()方法中执行耗时的操作。

知识点36

Fragment生命周期场景演示:

1.切换到该Fragment

11-29 14:26:35.095: D/AppListFragment(7649): onAttach11-29 14:26:35.095: D/AppListFragment(7649): onCreate11-29 14:26:35.095: D/AppListFragment(7649): onCreateView11-29 14:26:35.100: D/AppListFragment(7649): onActivityCreated11-29 14:26:35.120: D/AppListFragment(7649): onStart11-29 14:26:35.120: D/AppListFragment(7649): onResume
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.屏幕灭掉:

11-29 14:27:35.185: D/AppListFragment(7649): onPause11-29 14:27:35.205: D/AppListFragment(7649): onSaveInstanceState11-29 14:27:35.205: D/AppListFragment(7649): onStop
  • 1
  • 2
  • 3

3.屏幕解锁

11-29 14:33:13.240: D/AppListFragment(7649): onStart11-29 14:33:13.275: D/AppListFragment(7649): onResume
  • 1
  • 2

4.切换到其他Fragment:

11-29 14:33:33.655: D/AppListFragment(7649): onPause11-29 14:33:33.655: D/AppListFragment(7649): onStop11-29 14:33:33.660: D/AppListFragment(7649): onDestroyView
  • 1
  • 2
  • 3

5.切换回本身的Fragment:

11-29 14:33:55.820: D/AppListFragment(7649): onCreateView11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated11-29 14:33:55.825: D/AppListFragment(7649): onStart11-29 14:33:55.825: D/AppListFragment(7649): onResume
  • 1
  • 2
  • 3
  • 4

6.回到桌面

11-29 14:34:26.590: D/AppListFragment(7649): onPause11-29 14:34:26.880: D/AppListFragment(7649): onSaveInstanceState11-29 14:34:26.880: D/AppListFragment(7649): onStop
  • 1
  • 2
  • 3

7.回到应用

11-29 14:36:51.940: D/AppListFragment(7649): onStart11-29 14:36:51.940: D/AppListFragment(7649): onResume
  • 1
  • 2

8.退出应用

11-29 14:37:03.020: D/AppListFragment(7649): onPause11-29 14:37:03.155: D/AppListFragment(7649): onStop11-29 14:37:03.155: D/AppListFragment(7649): onDestroyView11-29 14:37:03.165: D/AppListFragment(7649): onDestroy11-29 14:37:03.165: D/AppListFragment(7649): onDetach
  • 1
  • 2
  • 3
  • 4
  • 5

知识点37 
高度注意Map类集合k/v存储null值的情况,如下表格:

这里写图片描述

知识点38 
ListView卡顿的原因与性能优化:

1.重用converView: 通过复用converview来减少不必要的view的创建,另外Infalte操作会把xml文件实例化成相应的View实例,属于IO操作,是耗时操作。

2.减少findViewById()操作: 将xml文件中的元素封装成viewholder静态类,通过converview的setTag和getTag方法将view与相应的holder对象绑定在一起,避免不必要的findviewbyid操作。

3.避免在 getView 方法中做耗时的操作: 例如加载本地 Image 需要载入内存以及解析 Bitmap ,都是比较耗时的操作,如果用户快速滑动listview,会因为getview逻辑过于复杂耗时而造成滑动卡顿现象。用户滑动时候不要加载图片,待滑动完成再加载,可以使用这个第三方库glide

4.Item的布局层次结构尽量简单,避免布局太深或者不必要的重绘。

5.尽量能保证 Adapter 的 hasStableIds() 返回 true 这样在 notifyDataSetChanged() 的时候,如果item内容并没有变化,ListView 将不会重新绘制这个 View,达到优化的目的。

6.在一些场景中,ScollView内会包含多个ListView,可以把listview的高度写死固定下来。 由于ScollView在快速滑动过程中需要大量计算每一个listview的高度,阻塞了UI线程导致卡顿现象出现,如果我们每一个item的高度都是均匀的,可以通过计算把listview的高度确定下来,避免卡顿现象出现。

7.使用 RecycleView 代替listview: 每个item内容的变动,listview都需要去调用notifyDataSetChanged来更新全部的item,太浪费性能了。RecycleView可以实现当个item的局部刷新,并且引入了增加和删除的动态效果,在性能上和定制上都有很大的改善。

8.ListView 中元素避免半透明: 半透明绘制需要大量乘法计算,在滑动时不停重绘会造成大量的计算,在比较差的机子上会比较卡。 在设计上能不半透明就不不半透明。实在要弄就把在滑动的时候把半透明设置成不透明,滑动完再重新设置成半透明。

9.尽量开启硬件加速: 硬件加速提升巨大,避免使用一些不支持的函数导致含泪关闭某个地方的硬件加速。当然这一条不只是对 ListView。


原创粉丝点击