Android性能优化

冷启动优化

    在application中可以的都放子线程加载,但是又要处理好多进程oncreate()方法多次执行初始化的问题

把主线程的串行任务变成并发任务

public abstract class BaseApplication extends Application
    implements java.lang.Thread.UncaughtExceptionHandler {

  protected static Application mContext = null;

  public static Context getAppContext() {
    return mContext;
  }

  @Override public void onCreate() {
    super.onCreate();
    mContext = this;
    long time2 = System.currentTimeMillis();
    if (ProcessUtils.isMainProcess()) {
      Thread.setDefaultUncaughtExceptionHandler(this);// todo 主线程 loggen失效去除、清除数据逻辑严谨去除
      initRxProperties();
      MMKV.initialize(this);
      RunUtils.runByIOThread(() -> {
        long time = System.currentTimeMillis();
        doBaseServiceThread();
        Log.e("lm", "服务线程 消耗 -->" + (System.currentTimeMillis() - time));
      });

      RunUtils.runByIOThread(() -> {
        long time = System.currentTimeMillis();
        doThirdThread();
        Log.e("lm", "ad线程 消耗 -->" + (System.currentTimeMillis() - time));
      });

      RunUtils.runByIOThread(() -> {
        long time = System.currentTimeMillis();
        DeviceScreenUtils.mDensity = ScreenUtils.getScreenDensity();
        DeviceScreenUtils.mDensityDpi = ScreenUtils.getScreenDensityDpi();
        DeviceScreenUtils.mDeviceWidth =
            getResources().getDisplayMetrics().widthPixels; //todo 替换真正的宽度
        DeviceScreenUtils.mDeviceHeight = getResources().getDisplayMetrics().heightPixels;
        doDataServiceThread();
        MemoryControlUtil.initCheckMaxCacheService(mContext);
        Log.e("lm", "数据线程 消耗 -->" + (System.currentTimeMillis() - time));
      });

      doMainThread();
      Log.e("lm", "主线程 消耗 -->" + (System.currentTimeMillis() - time2));
    }

    doOtherProccess();
    Log.e("lm", "其他进程消耗 -->" + (System.currentTimeMillis() - time2));
  }

  protected abstract void doBaseServiceThread();

  protected abstract void doDataServiceThread();

  protected abstract void doThirdThread();

  protected abstract void doMainThread();

  protected abstract void doOtherProccess();

  /**
   * @description 解决Rx2.0问题
   */
  private void initRxProperties() {
    //解决 2.0 Error直接发给虚拟机 发生carsh
    RxJavaPlugins.setErrorHandler(throwable -> Log.e(throwable.getMessage(), "rxJavaErrorHandler"));
    //RxJava开启一个循环线程在后台默默回收Publisher,默认是1秒循环一次,但是这样比较耗费cpu,纯净后台检测时,cpu唤醒率无法达到标准。
    System.setProperty("rx2.purge-enabled", "true");
    System.setProperty("rx2.purge-period-seconds", "600");
  }

  /**
   * @description 崩溃处理
   */
  @Override public void uncaughtException(Thread thread, Throwable exception) {
    exception.printStackTrace();
    try {
      douncaughtException();
      ActivityManager.finishActivities();
      android.os.Process.killProcess(myPid());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  protected abstract void douncaughtException();

  //设置字体为默认大小,不随系统字体大小改而改变
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    if (newConfig.fontScale != 1)//非默认值
    {
      getResources();
    }
    super.onConfigurationChanged(newConfig);
  }

  @Override
  public Resources getResources() {
    Resources res = super.getResources();
    if (res.getConfiguration().fontScale != 1) {//非默认值
      Configuration newConfig = new Configuration();
      newConfig.setToDefaults();//设置默认
      res.updateConfiguration(newConfig, res.getDisplayMetrics());
    }
    return res;
  }
}

任务调度的先后顺序

每个任务用countDownLatch来标记入度。

 

任务执行等待问题

我们实际开发中,经常会遇到这种场景,splashActivity的启动必须依赖于某个库初始化完成才行,直白一点来说就是在application中阻塞执行这个任务,基于我们的多线程并发任务调度,最简便的方法就是任务管理器使用CountDownLatch,在任务开始执行时调用countDownLatch.await(),在我们构造图结构时,把需要在application中阻塞执行的任务标记好,然后每执行完一个任务countDownLatch.countDown(),直到所有阻塞任务都执行完毕后,阻塞结束

首页和主页预加载

这部分属于小优化了,带来的冷启动时间的减少仅仅有1-3ms左右,就是我们可以在启动任务中加入一个任务,这个任务只做一件事:

SplashActivity spActivity = new SplashActivity();
MainActivity mainActivity = new MainActivity();

原理其实很简单,类加载器加载过一次类后,会缓存起来,再次加载该类时,不会再去findClass,上面的代码作用就是如此,我们真正创建Activity时,是通过反射创建的,findClass不仅仅是find还包含检查的作用(如 not find之类的try catch),所以这样做也可以节约部分时间 

可以加入一些配置以增加体验,比如加入Activity的background

方案1:

1、先为主界面单独写一个主题style,设置一张待显示的图片,这里我设置了一个颜色,然后在manifest中设置给MainActivity:

<style name="AppTheme.Launcher">
 <item name="android:windowBackground">@drawable/bule</item>
</style>
//...
  <activity
   android:name=".MainActivity"
   android:label="@string/app_name"
   android:theme="@style/AppTheme.Launcher">
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
  </activity>

 

2、然后在MainActivity中加载布局前把AppTheme重新设置给MainActivity:

@Override
 protected void onCreate(Bundle savedInstanceState) {
 
  setTheme(R.style.AppTheme);
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
} 

这样在启动时会先显示background,然后待界面绘制完成再显示主界面:

方案2:通过设置Style (1)设置背景图Theme 通过设置一张背景图。 当程序启动时,首先显示这张背景图,避免出现黑屏

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:screenOrientation">portrait</item>
        <item name="android:windowBackground">>@mipmap/splash</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
</style>

(2)设置透明Theme 通过把样式设置为透明,程序启动后不会黑屏而是整个透明了,等到界面初始化完才一次性显示出来

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:screenOrientation">portrait</item>
    </style>

 

两者对比: Theme1 程序启动快,界面先显示背景图,然后再刷新其他界面控件。给人刷新不同步感觉。 Theme2 给人程序启动慢感觉,界面一次性刷出来,刷新同步。 (3)修改AndroidManifest.xml

 <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true">
        <activity android:name=".MainActivity"
         android:theme="@style/AppTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    //......

</application>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值