android知识点

基础

Activity和Fragment生命周期有哪些?javascript


 


横竖屏切换时候Activity的生命周期java

不设置Activity的android:configChanges时,切屏会从新掉哟过各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
设置Activity的android:configChanges=”orientation”时,切屏仍是会调用各个生命周期,切换横竖屏只会执行一次
设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会从新调用各个生命周期,只会执行onConfigurationChanged方法android

默认状况下,切换屏幕方向时Activity会销毁、重建
onPause->onStop->onDestroy->onCreate->onStart->onResume
配置为android:configChanges=”orientation|screenSize”时web

AsyncTask
源码解析
AsyncTask的缺陷和问题数据库

关于线程池:asynctask对应的线程池ThreadPoolExecutor都是进程范围内共享的,都是static的,因此是asynctask控制着进程范围内全部的子类实例。因为这个限制的存在,当使用默认线程池时,若是线程数超过线程池的最大容量,线程池就会爆掉(3.0后默认串行执行,不会出现这个问题)。针对这种状况,能够尝试自定义线程池,配合asynctask使用。json

关于默认线程池:核心线程池中最多有CPU_COUNT+1个,最多有CPU_COUNT*2+1个,线程等待队列的最大等待数为128,可是能够自定义线程池。线程池是由AsyncTask来管理的,线程池容许tasks并行运行,xuyao注意的是并发状况下数据的一致性问题,新数据可能会被老数据覆盖掉,相似volatile变量。因此但愿tasks可以串行运行的话,使用SERIAL_EXECUTOR。安全

自定义线程池:executeOnExecutor(Executor exec,Params… params) 自定义Executor网络

execute(Params… params){return executeOnExecutor(sDefaultExecutor,params);}架构

AsyncTask在不一样的SDK版本中的区别:并发

调用AsyncTask的excute方法不能当即执行程序的缘由分析及改善方案

经过查阅官方文档发现,AsyncTask首次引入时,异步任务是在一个独立的线程中顺序的执行,也就是说一次只能执行一个任务,不能并行的执行,从1.6开始,AsyncTask引入了线程池,支持同时执行5个异步任务,也就是说同时只能有5个线程运行,超过的线程只能等待,等待前面的线程某个执行完了才被调度和运行。换句话说,若是一个进程中的AsyncTask实例个数超过5个,那么假如前5个都运行很长时间的话,那么第6个只能等待机会了。这是AsyncTask的一个限制,并且对于2.3之前的版本没法解决。若是你的应用须要大量的后台线程去执行任务,那么你只能放弃使用AsyncTask,本身建立线程池来管理Thread,或者干脆不用线程池直接使用Thread也无妨。不得不说,虽然AsyncTask较Thread使用起来方便,可是它最多只能同时运行5个线程,这也大大局限了它的实力,你必需要当心设计你的应用,错开使用AsyncTask的时间,尽力作到分时,或者保证数量不会大于5个,不然就会遇到上次提到的问题。多是Google意识到了AsyncTask的局限性了,从Android3.0开始对AsyncTask的API做出了一些调整:每次只启动一个线程执行一个任务,完成以后再执行第二个任务,也就是至关于只有一个后台线程在执行所提交的任务。

1.生命周期

不少开发者会认为一个在Activity中建立的AsyncTask会随着Activity的销毁而销毁。然而事实并不是如此。AsyncTask会一直执行,直到doInBackground()方法执行完毕。而后,若是cancel(boolean)被调用,那么onCancelled(Result result)方法会被执行;不然,执行onPostExecute(Result result)方法。若是咱们的Activity销毁以前,没有取消AsyncTask,这有可能让咱们的AsyncTask崩溃(crash)。由于它想要处理的view已经不在了。因此,咱们老是必须确保在销毁活动以前取消任务。总之,咱们使用AsyncTask须要确保AsyncTask正确的取消。

2.内存泄漏

若是AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对Activity的引用。若是Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,致使Activity没法被回收,引发内存泄漏。

3.结果丢失

屏幕旋转或Activity在后台被系统杀掉等状况会致使Activity的从新建立,以前运行的AsyncTask会持有一个以前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将再也不生效。

4.并行仍是串行

在Android1.6以前的版本,AsyncTask是串行的,在1.6至2.3的版本,改为了并行的。在2.3以后的版本又作了 修改,能够支持并行和串行,当想要串行执行时,直接执行execute()方法,若是须要执行executeOnExecutor(Executor)。

自定义View的相关方法 1.自定义属性
2.onLayout(Viewgroup)
3.onMesure
4.onDraw
5.交互: onIntercepterTouchEvent()
onTouchEvent()

android中进程的优先级?
前台进程
可见进程
服务进程
后台进程
空进程

Serializable和Parcelable
序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象能够在网络上进行传输,也能够存储到本地。
Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象能够在网络上进行传输,也能够存储到本地。

Parcelable(android 专用):
除了Serializable以外,使用Parcelable也能够实现相同的效果,
不过不一样于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

文件和数据库哪一个效率高
大量读取数据数据库更高效

Android系统启动过程,App启动过程
]从桌面点击到activity启动的过程

1.Launcher线程捕获onclick的点击事件,调用Launcher.startActivitySafely,进一步调用Launcher.startActivity,最后调用父类Activity的startActivity。

2.Activity和ActivityManagerService交互,引入Instrumentation,将启动请求交给Instrumentation,调用Instrumentation.execStartActivity。

3.调用ActivityManagerService的startActivity方法,这里作了进程切换(具体过程请查看源码)。

4.开启Activity,调用onCreate方法

事件传递机制 详解
当手指触摸到屏幕时,系统就会调用相应View的onTouchEvent,并传入一系列的action。

dispatchTouchEvent的执行顺序为:

首先触发ACTIVITY的dispatchTouchEvent,而后触发ACTIVITY的onUserInteraction
而后触发LAYOUT的dispatchTouchEvent,而后触发LAYOUT的onInterceptTouchEvent
这就解释了重写ViewGroup时必须调用super.dispatchTouchEvent();

(1)dispatchTouchEvent:

此方法通常用于初步处理事件,由于动做是由此分发,因此一般会调用super.dispatchTouchEvent。这样就会继续调用onInterceptTouchEvent,再由onInterceptTouchEvent决定事件流向。

(2)onInterceptTouchEvent:

若返回值为true事件会传递到本身的onTouchEvent();若返回值为false传递到下一个View的dispatchTouchEvent();

(3)onTouchEvent():

若返回值为true,事件由本身消耗,后续动做让其处理;若返回值为false,本身不消耗事件了,向上返回让其余的父View的onTouchEvent接受处理

三大方法关系的伪代码:若是当前View拦截事件,就交给本身的onTouchEvent去处理,不然就丢给子View继续走相同的流程。

public boolean dispatchTouchEvent(MotionEvent ev) { boolean consume = false; if(onInterceptTouchEvent(ev)) { consume = onTouchEvent(ev); } else { consume = child.dispatchTouchEvent(ev); } return consume; }

onTouchEvent的传递:

当有多个层级的View时,在父层级容许的状况下,这个action会一直传递直到遇到最深层的View。因此touch事件最早调用的是最底层View的onTouchEvent,若是View的onTouchEvent接收到某个touch action并作了相应处理,最后有两种返回方式return true和return false;return true会告诉系统当前的View须要处理此次的touch事件,之后的系统发出的ACTION_MOVE,ACTION_UP仍是须要继续监听并接收的,而且此次的action已经被处理掉了,父层的View是不可能触发onTouchEvent的了。因此每个action最多只能有一个onTouchEvent接口返回true。若是返回false,便会通知系统,当前View不关心这一次的touch事件,此时这个action会传向父级,调用父级View的onTouchEvent。可是这一次的touch事件以后发出任何action,该View都不在接受,onTouchEvent在这一次的touch事件中不再会触发,也就是说一旦View返回false,那么以后的ACTION_MOVE,ACTION_UP等ACTION就不会在传入这个View,可是下一次touch事件的action仍是会传进来的。

父层的onInterceptTouchEvent

前面说了底层的View可以接收到此次的事件有一个前提条件:在父层容许的状况下。假设不改变父层级的dispatch方法,在系统调用底层onTouchEvent以前会调用父View的onInterceptTouchEvent方法判断,父层View是否要截获本次touch事件以后的action。若是onInterceptTouchEvent返回了true,那么本次touch事件以后的全部action都不会向深层的View传递,通通都会传给父层View的onTouchEvent,就是说父层已经截获了此次touch事件,以后的action也没必要询问onInterceptTouchEvent,在此次的touch事件以后发出的action时onInterceptTouchEvent不会再被调用,直到下一次touch事件的来临。若是onInterceptTouchEvent返回false,那么本次action将发送给更深层的View,而且以后的每一次action都会询问父层的onInterceptTouchEvent需不须要截获本次touch事件。只有ViewGroup才有onInterceptTouchEvent方法,由于一个普通的View确定是位于最深层的View,只有ViewGroup才有onInterceptTouchEvent方法,由于一个普通的View确定是位于最深层的View,touch可以传到这里已是最后一站了,确定会调用View的onTouchEvent()。

底层View的getParent().requestDisallowInterceptTouchEvent(true)

对于底层的View来讲,有一种方法能够阻止父层的View获取touch事件,就是调用getParent().requestDisallowInterceptTouchEvent(true)方法。一旦底层View收到touch的action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也没法截获之后的action(若是父层ViewGroup和最底层View须要截获不一样焦点,或不一样手势的touch,不能使用这个写死)。

曾经开发过程当中遇到的两个示例:左边是处理ViewPager和ListView的冲突,纪录水平和垂直方向的偏移量,若是水平方向的偏移更多的话就让ViewPager处理pager滑动

右边处理的ViewPager和ImageBanner的滑动冲突,一样是纪录偏移量,若是发生在ImageBanner上的水平偏移量大于垂直偏移量的话就让banner滚动

想一想为何右边是重写dispatchTouchEvent方法而不是onInterceptTouchEvent方法?

FixedViewPager
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch(ev.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mX = ev.getX(); mY = ev.getY(); break; case MotionEvent.ACTION_MOVE: float x = ev.getX(); float y = ev.getY(); float dX = x - mX; float dY = y - mY; float tmp = Math.abs(dX) / Math.abs(dY); mX = x; mY = y; if(tmp > 1) { return true; } else { return super.omInterceptTouchEvent(ev); } } } FixedImageLoadBanner @override public boolean dispatchTouchEvent(MotionEvent ev) { if(mX != 0 || mY != 0) { float dY = ev.getRawY() - mY; float dX = ev.getRawX() - mX; if(Math.abs(dY) > Math.abs(dX)) { requestDisallowInterceptTouchEvent(false); } else { requestDisallowInterceptTouchEvent(true); } } mX = ev.getRawX(); mY = ev.getRawY(); return super.dispatchTouchEvent(ev); }

ART和Dalvik区别

art上应用启动快,运行快,可是耗费更多存储空间,安装时间长,总的来讲ART的功效就是”空间换时间”。

ART: Ahead of Time Dalvik: Just in Time

什么是Dalvik:Dalvik是Google公司本身设计用于Android平台的Java虚拟机。Dalvik虚拟机是Google等厂商合做开发的Android移动设备平台的核心组成部分之一,它能够支持已转换为.dex(即Dalvik Executable)格式的Java应用程序的运行,.dex格式是专为Dalvik应用设计的一种压缩格式,适合内存和处理器速度有限的系统。Dalvik通过优化,容许在有限的内存中同时运行多个虚拟机的实例,而且每个Dalvik应用做为独立的Linux进程执行。独立的进程能够防止在虚拟机崩溃的时候全部程序都被关闭。

什么是ART:Android操做系统已经成熟,Google的Android团队开始将注意力转向一些底层组件,其中之一是负责应用程序运行的Dalvik运行时。Google开发者已经花了两年时间开发更快执行效率更高更省电的替代ART运行时。ART表明Android Runtime,其处理应用程序执行的方式彻底不一样于Dalvik,Dalvik是依靠一个Just-In-Time(JIT)编译器去解释字节码。开发者编译后的应用代码须要经过一个解释器在用户的设备上运行,这一机制并不高效,但让应用能更容易在不一样硬件和架构上运行。ART则彻底改变了这套作法,在应用安装的时候就预编译字节码到机器语言,这一机制叫Ahead-Of-Time(AOT)编译。在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。

ART优势:

系统性能的显著提高
应用启动更快、运行更快、体验更流畅、触感反馈更及时。
更长的电池续航能力
支持更低的硬件
ART缺点:

更大的存储空间占用,可能会增长10%-20%
更长的应用安装时间

Scroller原理

Scroller执行流程里面的三个核心方法

mScroller.startScroll()
mScroller.computeScrollOffset()
view.computeScroll()
一、在mScroller.startScroll()中为滑动作了一些初始化准备,好比:起始坐标,滑动的距离和方向以及持续时间(有默认值),动画开始时间等。

二、mScroller.computeScrollOffset()方法主要是根据当前已经消逝的时间来计算当前的坐标点。由于在mScroller.startScroll()中设置了动画时间,那么在computeScrollOffset()方法中依据已经消逝的时间就很容易获得当前时刻应该所处的位置并将其保存在变量mCurrX和mCurrY中。除此以外该方法还可判断动画是否已经结束。

Android中Java和JavaScript交互

webView.addJavaScriptInterface(new Object(){xxx}, "xxx"); 1 答案:可使用WebView控件执行JavaScript脚本,而且能够在JavaScript中执行Java代码。要想让WebView控件执行JavaScript,须要调用WebSettings.setJavaScriptEnabled方法,代码以下: WebView webView = (WebView)findViewById(R.id.webview); WebSettings webSettings = webView.getSettings(); //设置WebView支持JavaScript webSettings.setJavaScriptEnabled(true); webView.setWebChromeClient(new WebChromeClient()); JavaScript调用Java方法须要使用WebView.addJavascriptInterface方法设置JavaScript调用的Java方法,代码以下: webView.addJavascriptInterface(new Object() { //JavaScript调用的方法 public String process(String value) { //处理代码 return result; } }, "demo"); //demo是Java对象映射到JavaScript中的对象名 可使用下面的JavaScript代码调用process方法,代码以下: <script language="javascript"> function search() { //调用searchWord方法 result.innerHTML = "<font color='red'>" + window.demo.process('data') + "</font>"; }

SurfaceView和View的最本质的区别

SurfaceView是在一个新起的单独线程中能够从新绘制画面,而view必须在UI的主线程中更新画面。

在UI的主线程中更新画面可能会引起问题,好比你更新的时间过长,那么你的主UI线程就会被你正在画的函数阻塞。那么将没法响应按键、触屏等消息。当使用SurfaceView因为是在新的线程中更新画面因此不会阻塞你的UI主线程。但这也带来了另一个问题,就是事件同步。好比你触屏了一下,你须要SurfaceView中thread处理,通常就须要有一个event queue的设计来保存touchevent,这会稍稍复杂一点,由于涉及到线程安全。

ANR排错

一、ANR排错通常有三种类型

  • KeyDispatchTimeout(5 seconds) –主要类型按键或触摸事件在特定时间内无响应
  • BroadcastTimeout(10 secends) –BroadcastReceiver在特定时间内没法处理完成
  • ServiceTimeout(20 secends) –小几率事件 Service在特定的时间内没法处理完成
  • 二、如何避免

UI线程尽可能只作跟UI相关的工做
耗时的操做(好比数据库操做,I/O,链接网络或者别的有可能阻塞UI线程的操做)把它放在单独的线程处理
尽可能用Handler来处理UIthread和别的thread之间的交互.
三、如何排查

首先分析log
从trace.txt文件查看调用stack,adb pull data/anr/traces.txt ./mytraces.txt
看代码
仔细查看ANR的成因(iowait?block?memoryleak?)
四、监测ANR的Watchdog

Android 内存溢出解决方案(OOM) 整理总结

  • 在内存引用上作些处理,经常使用的有软引用、弱引用
  • 在内存中加载图片时直接在内存中做处理,如:边界压缩
  • 动态回收内存
  • 优化Dalvik虚拟机的堆内存分配
  • 自定义堆内存大小

动画详解

View绘制流程

断电续传

Handler机制
andriod提供了Handler 和 Looper 来知足线程间的通讯。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。
Looper: 一个线程能够产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。
Handler: 你能够构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。
Message Queue(消息队列):用来存放线程放入的消息。
线程:UIthread 一般就是main thread,而Android启动程序时会替它创建一个MessageQueue。

ListView卡顿缘由
Adapter的getView方法里面convertView没有使用setTag和getTag方式;
在getView方法里面ViewHolder初始化后的赋值或者是多个控件的显示状态和背景的显示没有优化好,抑或是里面含有复杂的计算和耗时操做;
在getView方法里面 inflate的row 嵌套太深(布局过于复杂)或者是布局里面有大图片或者背景所致;
Adapter多余或者不合理的notifySetDataChanged;
listview 被多层嵌套,屡次的onMessure致使卡顿,若是多层嵌套没法避免,建议把listview的高和宽设置为fill_parent. 若是是代码继承的listview,那么也请你别忘记为你的继承类添加上LayoutPrams,注意高和宽都是fill_parent的;

启动一个程序,能够主界面点击图标进入,也能够从一个程序中跳转过去,两者有什么区别?
是由于启动程序(主界面也是一个app),发现了在这个程序中存在一个设置为

<category android:name="android.intent.category.LAUNCHER" />的activity,

因此这个launcher会把icon提出来,放在主界面上。当用户点击icon的时候,发出一个Intent:

Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);

跳过去能够跳到任意容许的页面,如一个程序能够下载,那么真正下载的页面可能不是首页(也有多是首页),这时仍是构造一个Intent,startActivity.
这个intent中的action可能有多种view,download都有可能。系统会根据第三方程序向系统注册的功能,为你的Intent选择能够打开的程序或者页面。因此惟一的一点
不一样的是从icon的点击启动的intent的action是相对单一的,从程序中跳转或者启动可能样式更多一些。本质是相同的。

优化

界面优化
太多重叠的背景(overdraw)

这个问题其实最容易解决,建议就是检查你在布局和代码中设置的背景,有些背景是隐藏在底下的,它永远不可能显示出来,这种不必的背景必定要移除,由于它极可能会严重影响到app的性能。若是采用的是selector的背景,将normal状态的color设置为”@android:color/transparent”,也一样能够解决问题。

太多重叠的View

第一个建议是 :是哟过ViewStub来加载一些不经常使用的布局,它是一个轻量级且默认是不可见的视图,能够动态的加载一个布局,只要你用到这个重叠着的View的时候才加载,推迟加载的时间。

第二个建议是:若是使用了相似Viewpager+Fragment这样的组合或者有多个Fragment在一个界面上,须要控制Fragment的显示和隐藏,尽可能使用动态的Inflation view,它的性能要比SetVisibility好。

复杂的Layout层级

这里的建议比较多一些,首先推荐使用Android提供的布局工具Hierarchy Viewer来检查和优化布局。第一个建议是:若是嵌套的线性布局加深了布局层次,可使用相对布局来取代。第二个建议是:用标签来合并布局。第三个建议是:用标签来重用布局,抽取通用的布局可让布局的逻辑更清晰明了。记住,这些建议的最终目的都是使得你的Layout在Hierarchy Viewer里变得宽而浅,而不是窄而深。

使用merge和include,ViewStub。

移动端获取网络数据优化的几个点

链接复用:节省链接创建时间,如开启 keep-alive。
对于Android来讲默认状况下HttpURLConnection和HttpClient都开启了keep-alive。只是2.2以前HttpURLConnection存在影响链接池的Bug,具体可见:Android HttpURLConnection及HttpClient选择

请求合并:即将多个请求合并为一个进行请求,比较常见的就是网页中的CSS Image Sprites。若是某个页面内请求过多,也能够考虑作必定的请求合并。

减小请求数据的大小:对于post请求,body能够作gzip压缩的,header也能够作数据压缩(不过只支持http 2.0)。
返回数据的body也能够作gzip压缩,body数据体积能够缩小到原来的30%左右。(也能够考虑压缩返回的json数据的key数据的体积,尤为是针对返回数据格式变化不大的状况,支付宝聊天返回的数据用到了)
根据用户的当前的网络质量来判断下载什么质量的图片(电商用的比较多)



文/maat红飞(简书做者) 原文连接:http://www.jianshu.com/p/89f19d67b348 著做权归做者全部,转载请联系做者得到受权,并标注“简书做者”。
相关文章
相关标签/搜索