Android当中保持60帧以上算是流畅:60fps ——>16ms/帧(数字量化)java
准则:尽可能保证每次在16ms内处理完全部的cpu与Gpu计算、绘制、渲染等操做,不然会形成丢帧卡顿等问题android
缘由:在主线程中执行耗时工做,把事件分发给合适的view或者widget的git
handler
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
复制代码
布局Layout过于复杂,没法在16ms内完成渲染github
View的过分绘制安全
View频繁的触发measure、layoutbash
内存频繁的触发GC过多(STW,建立太多的临时变量)实现的核心原理网络
###Blockcanary工具 在主线程ActivityThread中的 dispatchMessge(msg)上下方打印时间,计算阀值,超过了就打印并发
postMessage(Handler)app
Queue.next()获取咱们的消息less
是否超过咱们的阀值 (Dump all Allocation)
DisplayActivity在 release 版本不会显示
核心逻辑在BlockCanaryInternals:
LooperMonitor:判断是否卡顿 isBlock
private boolean isBlock(long endTime) {
return endTime - mStartTimestamp > mBlockThresholdMillis;
}
private void notifyBlockEvent(final long endTime) {
final long startTime = mStartTimestamp;
final long startThreadTime = mStartThreadTimestamp;
final long endThreadTime = SystemClock.currentThreadTimeMillis();
HandlerThreadFactory.getWriteLogThreadHandler().post(new Runnable() {
@Override
public void run() {
mBlockListener.onBlockEvent(startTime, endTime, startThreadTime, endThreadTime);
}
});
}
private void startDump() {
if (null != BlockCanaryInternals.getInstance().stackSampler) {
BlockCanaryInternals.getInstance().stackSampler.start();
}
if (null != BlockCanaryInternals.getInstance().cpuSampler) {
BlockCanaryInternals.getInstance().cpuSampler.start();
}
}
复制代码
stackSampler:
public ArrayList<String> getThreadStackEntries(long startTime, long endTime) {
ArrayList<String> result = new ArrayList<>();
synchronized (sStackMap) {
for (Long entryTime : sStackMap.keySet()) {
if (startTime < entryTime && entryTime < endTime) {
result.add(BlockInfo.TIME_FORMATTER.format(entryTime)
+ BlockInfo.SEPARATOR
+ BlockInfo.SEPARATOR
+ sStackMap.get(entryTime));
}
}
}
return result;
}
@Override
protected void doSample() {
StringBuilder stringBuilder = new StringBuilder();
for (StackTraceElement stackTraceElement : mCurrentThread.getStackTrace()) {
stringBuilder
.append(stackTraceElement.toString())
.append(BlockInfo.SEPARATOR);
}
synchronized (sStackMap) {
if (sStackMap.size() == mMaxEntryCount && mMaxEntryCount > 0) {
sStackMap.remove(sStackMap.keySet().iterator().next());
}
sStackMap.put(System.currentTimeMillis(), stringBuilder.toString());
}
}
复制代码
CpuSampler:
@Override
protected void doSample() {
BufferedReader cpuReader = null;
BufferedReader pidReader = null;
try {
cpuReader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/stat")), BUFFER_SIZE);
String cpuRate = cpuReader.readLine();
if (cpuRate == null) {
cpuRate = "";
}
if (mPid == 0) {
mPid = android.os.Process.myPid();
}
pidReader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/" + mPid + "/stat")), BUFFER_SIZE);
String pidCpuRate = pidReader.readLine();
if (pidCpuRate == null) {
pidCpuRate = "";
}
parse(cpuRate, pidCpuRate);
} catch (Throwable throwable) {
Log.e(TAG, "doSample: ", throwable);
} finally {
try {
if (cpuReader != null) {
cpuReader.close();
}
if (pidReader != null) {
pidReader.close();
}
} catch (IOException exception) {
Log.e(TAG, "doSample: ", exception);
}
}
}
复制代码
watchDog-anr是如何监控anr的?
主线程耗时操做 ()
主线程被锁住
cpu被其它的进程占用
建立一个监控线程
private final Handler _uiHandler = new Handler(Looper.getMainLooper());
复制代码
改线程不断往UI线程post一个任务
private final Runnable _ticker = new Runnable() {
@Override public void run() {
_tick = (_tick + 1) % Integer.MAX_VALUE;
}
};
@Override
public void run() {
setName("|ANR-WatchDog|");
int lastTick;
int lastIgnored = -1;
while (!isInterrupted()) {
lastTick = _tick;
_uiHandler.post(_ticker);
try {
//睡眠固定时间
Thread.sleep(_timeoutInterval);
}
catch (InterruptedException e) {
_interruptionListener.onInterrupted(e);
return ;
}
// If the main thread has not handled _ticker, it is blocked. ANR.
if (_tick == lastTick) {
if (!_ignoreDebugger && Debug.isDebuggerConnected()) {
if (_tick != lastIgnored)
Log.w("ANRWatchdog", "An ANR was detected but ignored because the debugger is connected (you can prevent this with setIgnoreDebugger(true))");
lastIgnored = _tick;
continue ;
}
ANRError error;
if (_namePrefix != null)
error = ANRError.New(_namePrefix, _logThreadsWithoutStackTrace);
else
error = ANRError.NewMainOnly();
_anrListener.onAppNotResponding(error);
return;
}
}
}
复制代码
存在的问题:
Process.setThreadPriority(Process.THREAD_PRIO_RITY_BACKGROUD), 须要把线程优先级下降
Handler handler = new Handler(){
void handlerMessage(){
do UI things...
}
}
New Thread(){
void run(){
handler. sendMessage();
}
}.start();
handler.post(runnable);
Activity.runOnUiThread(Runnable)
复制代码
AsynTask的线程优先级是background不会阻塞UI。
AsyncTask 3.0以后改为顺序执行,当一个进程中有多个AsynTask同时并行执行,他们会公用线程池,主要缘由在doInBackground()中访问相同的资源,线程池会形成线程的并发访问形成线程安全问题,因此设计成串行的,就不会有线程安全问题。
Runnable做为匿名内部类的话会持有外部类的引用,容易内存泄漏,不建议采起这种方式
它集成了Thread
它有本身的内部Looper对象,经过Looper.loop()进行looper循环
HandlerThread的looper对象传递给Handler对象,而后在handleMessge()方法中执行异步任务
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/** * This method returns the Looper associated with this thread. If this thread not been started * @return The looper. */
//这个是在UI线程中调用,须要解决同步问题,由于looper对象在 run方法里运行。
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/** * @return a shared {@link Handler} associated with this thread * @hide */
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/** * Quits the handler thread's looper. * <p> * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. * @see #quitSafely */
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
//清空全部消息
looper.quit();
return true;
}
return false;
}
/** * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. */
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
//清除全部的延迟消息
looper.quitSafely();
return true;
}
return false;
}
/** * Returns the identifier of this thread. See Process.myTid(). */
public int getThreadId() {
return mTid;
}
}
复制代码
HandlerThread适合单线程或者异步队列,I/O流读取文件,进行异步转化比较合适,只有一个线程。
网络的数据须要并发处理,不太适合。
intentService是Service类的子类
单独开启一个线程来处理全部的Intent请求所对应的任务
当IntentService处理完任务以后,会本身在合适的时候结束
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/** * Unless you provide binding for your service, you don't need to implement this * method, because the default implementation returns null. * @see android.app.Service#onBind */
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
复制代码
//饿汉
public class Singleton{
private static Singleton intance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
//懒汉
public class SingletonLazy{
private static SingletonLazy intance = null;
private Singleton(){}
public static SingletonLazy getInstance(){
if(null == instance){
instance = new SingletonLazy();
}
return instance;
}
//性能损耗较大
public static synchronized SingletonLazy getInstance1(){
if(null == instance){
instance = new SingletonLazy();
}
return instance;
}
}
//双重校验锁
public class SingletonDouble{
private static volatile SingletonDouble intance = null;
private SingletonDouble(){}
public static SingletonDouble getInstance(){
if(null == instance){
synchronized(SingletonDouble.this){
if(null == instance){
instance = new SingletonDouble();
}
}
}
return instance;
}
}
复制代码