2022-03-01

WindowManagerService

//Activity
final void attach{
mWindow = new PhoneWindow(this, window, activityConfigCallback);
  //viewrootimpl 里点击回调的地方
 mWindow.setCallback(this);
  mWindow.setWindowManager(
              (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
              mToken, mComponent.flattenToString(),
              (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
}

//window 
public void setWindowManager{
      //mWindowManager = WindowManagerImpl
    // WindowManagerImpl 类似contextwrapper 的装饰者模式,他里面主要是一个 mGlobal
      也就是 WindowManagerGlobal 来执行真正的操作
      mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
  }


  @Override
  public void setContentView(int layoutResID) {
     //初始化DecorView
      if (mContentParent == null) {
          installDecor();
      } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
          mContentParent.removeAllViews();
      }

      if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
          final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                  getContext());
          transitionTo(newScene);
      } else {
          mLayoutInflater.inflate(layoutResID, mContentParent);
      }
      mContentParent.requestApplyInsets();
      final Callback cb = getCallback();
      if (cb != null && !isDestroyed()) {
          cb.onContentChanged();
      }
      mContentParentExplicitlySet = true;
  }

//ActivityThread
public void  handleResumeActivity {
    //这才真的吧view添加进window
      //WindowManagerImpl -> WindowManagerGlobal .addView()
      wm.addView(decor, l);
}

//WindowManagerGlobal 
//viewrootimpl 和decorview进行绑定
public void addView(View view, ViewGroup.LayoutParams params,
          Display display, Window parentWindow) {
   

      ViewRootImpl root;
   

          root = new ViewRootImpl(view.getContext(), display);

          view.setLayoutParams(wparams);

          mParams.add(wparams);

          root.setView(view, wparams, panelParentView);
      


//viewrootimpl

 public void setView{
    
  requestLayout();
}

@Override
  public void requestLayout() {
          //检查线程
          checkThread();
          scheduleTraversals();
     
  }
//编舞者监听 ,会通过handler接到异步消息,但这也是为什么onResume拿不到宽高
//因为在doTraversal 计算宽高,doTraversal 不在super.onResume里执行,而是后面回调回来的
void scheduleTraversals() {
      if (!mTraversalScheduled) {
          mTraversalScheduled = true;
          //同步屏障
          mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
          mChoreographer.postCallback(
                  Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
          if (!mUnbufferedInputDispatch) {
              scheduleConsumeBatchedInput();
          }
  
      }
  }
// performMeasure performLayout performDraw
final class TraversalRunnable implements Runnable {
      @Override
      public void run() {
          doTraversal();
      }
  }

SurfaceFlinger

整合各个surface数据,共同发给硬件

Surface

用来记录界面 的位置,大小颜色

SurfaceView, TextureView区别

TextureView

需要硬件加速
和个普通view一样,可以旋转动画
延迟比较高

SurfaceView

有自己独立windowstate 和layer

Surface

持有一个canvas
viewrootimpl 里canvas = mSurface.lockCanvas(dirty); 拿到canvas
同时 Surface.lockCanvas() 建立与sufaceFlinger的联系

先onResume 再onStop的流程

//ActivityThread
public void handleResumeActivity{

//最后一步,这个用来调用之前activity STOP
      Looper.myQueue().addIdleHandler(new Idler());

}

//Idler
public final boolean queueIdle() {
//activityManagerService
am.activityIdle(a.token, a.createdConfig, stopProfiling);
}

//ActivityManagerService
public final void activityIdle{
ActivityRecord r =
                      mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
                              false /* processPausingActivities */, config);
}
// ActivityStackSupervisor
final ActivityRecord activityIdleInternalLocked{
   stack.stopActivityLocked(r);
}

// ActivityStack
 final void stopActivityLocked{
//这里又回调回applicationThread啦,注意用的StopActivityItem,执行他的excute时
mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
                      StopActivityItem.obtain(r.visible, r.configChangeFlags));
}

//StopActivityItem
//ClientTransactionHandler 就是ActivityThread
  public void execute(ClientTransactionHandler client, IBinder token,
          PendingTransactionActions pendingActions) {
      Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
      client.handleStopActivity(token, mShowWindow, mConfigChanges, pendingActions,
              true /* finalStateRequest */, "STOP_ACTIVITY_ITEM");
      Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
  }

class 怎么判断相同

1, 类名+ 包名 相同
2,加载的 classLoader是同一个

classLoader

baseDexClassLoader -> DexPathList 包含

//我们新的dex 就可以放这里面
private Element[] dexElements;
//so 加载路径
NativeLibraryElement[] nativeLibraryPathElements;


网络优化

1,httpdns
2, 合并网络请求
3,keep-alive,多路复用
4, gizp压缩
5,Protocol Buffer
6,缓存

apk瘦身

1,图标
2,混淆
3,andGuard 修改resources.arsc
4,插件化(有版本维护问题,支付宝都改为网页了)

大图加载

先通过看要差多大,比如现在只有内存只有10K,我们要加载10m的
那就是inSampleSize = n. 缩小的 倍数 n^2 > 10m/10. n ^2 >= 1024
即n = 10 ,n会向下取2的整数次方,最后效果可能只有8,因此要判断如果不是i = log2 不是整数,不是就n = 2^(i%1+1)
//拿到剩下内存
Runtime.getRuntime().freeMemory();

    BitmapFactory.Options options = new BitmapFactory.Options();
    //只计算大小
    options.inJustDecodeBounds = true;
    //宽高都是1/3 总的是1/9 ,但是错了,inSampleSize 注释里写的是
    //any other value will be rounded down to the nearest power of 2.
    //也就是如果inSampleSize 会向下取2^n次方,比如你写3,应该就是2,你写10就是8
    options.inSampleSize = 3;
    Bitmap bitmap = BitmapFactory.decodeFile("xxx.png");

    //压缩图片 去磁盘
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
    byte[] bitmapdata = bos.toByteArray();

jvm 方法区会oom嘛

参考链接
会的,比如加载了过多类,过多方法
1.6 永久代,字符串常量池 ,静态变量,常量,运行时常量池,类,方法,jit等信息
1.7 没有永久代,字符串常量池 ,静态变量移动到堆了
1.8 改为元空间

localSocket和socket区别

localSocket主要用于进程间通信,减少不必要的网络协议栈

如何寻找anr问题

anr /data/anr/trace.txt 里 tid =1的线程的日志栈

偏向锁 升级轻量级要stw,轻升重呢

轻升重不需要,偏向锁其实就是没锁,当他修改markdown信息为轻量锁的时候,担心别人也在用,所以要stw,但是轻升重,轻已经加锁了,所以不需要

app启动安全模式

检查是否启动 crash设置个flag = 上次的 flag+1(本地持久化)

1,如果app10秒以后退出,清空
2,如果用户手动到后台,清空
3, 正常生命流程退出,清空

通过flag进行级别判断

flag 清除无关紧要的数据
or
清除全部数据

判断有热修复配置,先进行热修复

binder

1,bindService会回调回主线程
2,bindService 最大线程数15
3,超过最大线程数会等待

静态内部类单例模式

jvm类用到才会加载,没用到不会加载,因此有延迟加载的作用

返回什么

public int tryFinallyReturn() {
  try {
      throw new Exception("return");
  } catch (Exception e) {
      return 0;
  } finally {
      return 1;
  }
}

返回1,因为try catch 和finlly的关系就是无论怎么样都会执行finally,如果t-c 过程中遇到return就先执行finlly,如果finally有return, 就不会执行t-c里的return了,毕竟能暂停return只有finally

zygote为什么不使用binder

愿意很简单,因为binder是多线程的,而fork不支持多线程,容易造成死锁等问题
zygote为什么不使用binder

okhttp 对一域名 最多几个链接

5个

android屏幕刷新机制

你可能感兴趣的:(2022-03-01)