-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
52 lines (52 loc) · 15.4 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Android性能分析的几种方法]]></title>
<url>%2F2019%2F01%2F19%2FAndroid%2FAndroid%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E7%9A%84%E5%87%A0%E7%A7%8D%E6%96%B9%E6%B3%95%2F</url>
<content type="text"><![CDATA[通过Memory Monitor 查找内存泄漏Android Profiler中的Memory Monitor可以实时查看app的内存占用情况。通过操作app界面,抓取某段时间的heap dump分析内存泄漏情况 这个图是从主页反复进入选择APP页面过程抓取的heap dump信息,通过搜索SelectAppActivity发现存在多个实例,存在内存泄漏无疑,要查找具体泄漏的原因需要用到mat工具。将刚才的heap dump导出文件,然后通过android 命令行工具hprof-conv转换为标准的heap dump,导入mat查看 然后通过path to GC Roots找到引用路径,发现是EventBus未注销引起的泄漏 LeakCanaryLeakCanary是square公司出的一个java/Android内存泄漏检测工具,具体使用见github:https://github.com/square/leakcanary 在apk运行过程中发生内存泄漏 使用Android Device Monitor中的TraceView分析性能TraceView有两种使用方法: 方法级别:在代码中手动开启,统计某一函数的耗时,会在sdcard中输出trace文件,导入ddms即可查看Debug.startMethodTracing('tracepath') Debug.stopMethodTracing() 时间段级别:通过ddms的Method Profiling或者Android Profile CPU中的method trace开启,用于统计一段时间内的函数耗时 比如分析list滚动性能,通过incl cpu time / call total 计算每个onBindingViewHolder耗时,来查看是否有阻塞操作]]></content>
<categories>
<category>技术</category>
</categories>
<tags>
<tag>Android</tag>
</tags>
</entry>
<entry>
<title><![CDATA[UML图理解]]></title>
<url>%2F2019%2F01%2F19%2FAndroid%2FUML%E5%9B%BE%E7%90%86%E8%A7%A3%2F</url>
<content type="text"><![CDATA[UML图是理解面向对象语言代码的利器。在开发中经常会使用到一些第三方库,在文档缺失的情况下,想快速了解代码结构,可以通过工具快速生成UML图来加速理解。我常用的开发工具是android studio,它有一个插件叫做simpleUML,可以很方便的生成UML图。 #理解UML uml图里面有6种关系,按照强弱排序是: 泛化(继承)= 实现 > 组合 > 聚合 > 关联 > 依赖 继承和实现比较好理解,对应java语言就是extends和implements。 组合、聚合都是关联的一种,代码层面表示就是成员变量,要区分它们只能从逻辑上来。 组合表示整体和部分的关系,这两者是不可分割的,例如鸽子和翅膀聚合也表示整体和部分的关系,但是弱一些,两者可分离,例如鸽子和鸽群关联是一种拥有关系,例如企鹅和气候 依赖是一种使用关系,代码层面就是局部变量、方法参数或静态方法下面这张图描述了这6种关系 参考:https://blog.csdn.net/tianhai110/article/details/6339565]]></content>
<categories>
<category>技术</category>
</categories>
<tags>
<tag>UML</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Ubuntu14.04 Android 源码编译相关]]></title>
<url>%2F2019%2F01%2F19%2FAndroid%2FUbuntu14-04-Android-%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E7%9B%B8%E5%85%B3%2F</url>
<content type="text"><![CDATA[参考:http://www.jianshu.com/p/367f0886e62bhttps://source.android.com/source/initializinghttps://mirrors.tuna.tsinghua.edu.cn/help/AOSP/ 1、环境相关首先保证电脑配置要够,cpu最好是4核以上的,因为编译的时候很耗费cpu,如果是4核双线程的,编译的时候可以起16个线程,make -j16,大大加快编译速度其次就是内存,最好是16G,如果是在虚拟机里面编译的话要开始swap分区,大小要超过16G最后就是硬盘,如果只编译一个版本的话150G是要得,多版本就200G+了。2、编译环境配置java配置sudo add-apt-repository ppa:openjdk-r/ppasudo apt-get updatesudo apt-get install openjdk-8-jdk如果装有多个版本的java,切换java版本sudo update-alternatives –config javasudo update-alternatives –config javacsudo update-alternatives –config javadoc编译各Android版本需要的java版本如下Android版本 编译要求的JDK版本AOSP的Android主线 OpenJDK 8Android 5.x至android 6.0 OpenJDK 7Android 2.3.x至Android 4.4.x Oracle JDK 6Android 1.5至Android 2.2.x Oracle JDK 5 配置编译工具链$ sudo apt-get install git-core gnupg flex bison gperf build-essential \ zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \ lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \ libgl1-mesa-dev libxml2-utils xsltproc unzip 3、源码下载下载 repo 工具: mkdir ~/binPATH=~/bin:$PATHcurl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repo > ~/bin/repochmod a+x ~/bin/repo建立工作目录:mkdir WORKING_DIRECTORYcd WORKING_DIRECTORY 初始化仓库:repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest 如果提示无法连接到 gerrit.googlesource.com,请参照git-repo的帮助页面的更新一节。如果需要某个特定的 Android 版本(列表):repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-4.0.1_r1 同步源码树(以后只需执行这条命令来同步):repo sync 4、编译源码初始化编译环境source build/envsetup.sh选择编译目标lunch aosp_arm64-eng开始编译make -j16运行模拟器emulator 5、问题内存不足在编译命令之前,修改prebuilts/sdk/tools/jack-admin文件,找到文件中的这一行:JACK_SERVER_COMMAND=”java -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME”然后在该行添加-Xmx4096m,如:JACK_SERVER_COMMAND=”java -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4096m -cp $LAUNCHER_JAR $LAUNCHER_NAME”]]></content>
<categories>
<category>技术</category>
</categories>
<tags>
<tag>Ubuntu</tag>
</tags>
</entry>
<entry>
<title><![CDATA[判断Fragment是否对用户可见]]></title>
<url>%2F2019%2F01%2F19%2FAndroid%2F%E5%88%A4%E6%96%ADFragment%E6%98%AF%E5%90%A6%E5%AF%B9%E7%94%A8%E6%88%B7%E5%8F%AF%E8%A7%81%2F</url>
<content type="text"><![CDATA[#引子最近在做应用内存优化,首要考虑优化的就是首页推荐位的图片。 上图Tab页是通过ViewPager+Fragment实现的,推荐页使用了Scrollview可以往下滚动因此推荐页有大量的图片,占用了大量的内存,需要做如下优化 #优化项1.进入推荐页时,只加载Scrollview中可见的图片2.离开推荐页时,释放Scrollview中不可见的图片3.点击图片进入详情页后,释放全部图片4.Scrollview滚动时只加载可见的图片 #技术点1.如何判断Fragment是否对用户可见 最容易想到的就是通过生命周期函数onPause()和onResume()来判断,但是在此viewpager中切换fragment,却未触发这两个生命周期函数。因为viewpager会默认加载当前页的前后页,而且还可通过setOffscreenPageLimit来设置默认加载多页。那有什么办法知道Fragment是否对用户可见呢?有的,具体分几种情况 ViewPager+Fragment因为Fragment懒加载机制的原因,切换时Fragment并未销毁,不会触发onPause(),因此需要用setUserVisibleHint()来判断123456789101112131415161718192021222324/** * Set a hint to the system about whether this fragment's UI is currently visible * to the user. This hint defaults to true and is persistent across fragment instance * state save and restore. * * <p>An app may set this to false to indicate that the fragment's UI is * scrolled out of visibility or is otherwise not directly visible to the user. * This may be used by the system to prioritize operations such as fragment lifecycle updates * or loader ordering behavior.</p> * * <p><strong>Note:</strong> This method may be called outside of the fragment lifecycle. * and thus has no ordering guarantees with regard to fragment lifecycle method calls.</p> * * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), * false if it is not. */ public void setUserVisibleHint(boolean isVisibleToUser) { if (!mUserVisibleHint && isVisibleToUser && mState < STARTED && mFragmentManager != null && isAdded()) { mFragmentManager.performPendingDeferredStart(this); } mUserVisibleHint = isVisibleToUser; mDeferStart = mState < STARTED && !isVisibleToUser; } ViewPager初始化时不会触发setUserVisibleHint(),只会在切换Fragment时 Activity+Fragmentxml引入fragment,或者通过addFragment、replaceFragment,直接判断onPause()和onResume()即可 FragmentManger show() hide()fragment没有被销毁,虽然不可见,但是不会触发onPause,需要用onHiddenChanged()来判断123456789@Overridepublic void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); if(hidden){ //TODO now visible to user } else { //TODO now invisible to user }} 2.如何判断View是否可见 判断View是否在屏幕中可见,可使用如下函数12345678910111213141516171819/** * 判断视图是否显示在屏幕上 * @param context * @param view * @return */ public static boolean checkIsVisible(Context context, View view) { int screenWidth = getScreenMetrics(context).x; int screenHeight = getScreenMetrics(context).y; Rect rect = new Rect(0, 0, screenWidth, screenHeight); int[] location = new int[2]; view.getLocationInWindow(location); if (view.getLocalVisibleRect(rect)) { return true; } else { //view已不在屏幕可见区域; return false; } } 3.如何判断View是否在ScrollView中可见 判断View是否在ScrollView中可见,可使用如下函数1234567891011private boolean isVisibleInScrollView(ScrollView scroll, View view) { Rect bounds = new Rect(); view.getHitRect(bounds); Rect scrollBounds = new Rect(scroll.getScrollX(), scroll.getScrollY(), scroll.getScrollX() + scroll.getWidth(), scroll.getScrollY() + scroll.getHeight()); if (Rect.intersects(scrollBounds, bounds)) { return true; } else { return false; } } 4.如何控制图片加载 控制图片加载我们不能直接使用View.setVisibility(View.VISIBLE|VIew.GONE),否则会视图需要重新渲染,引起操作时的卡顿。我们可以通过发送dispatchDisplayHint(int hint),然后在View中处理onDisplayHint(int hint)来控制图片加载1234567891011121314151617181920212223/** * Dispatch a hint about whether this view is displayed. For instance, when * a View moves out of the screen, it might receives a display hint indicating * the view is not displayed. Applications should not <em>rely</em> on this hint * as there is no guarantee that they will receive one. * * @param hint A hint about whether or not this view is displayed: * {@link #VISIBLE} or {@link #INVISIBLE}. */ public void dispatchDisplayHint(int hint) { onDisplayHint(hint); } /** * Gives this view a hint about whether is displayed or not. For instance, when * a View moves out of the screen, it might receives a display hint indicating * the view is not displayed. Applications should not <em>rely</em> on this hint * as there is no guarantee that they will receive one. * * @param hint A hint about whether or not this view is displayed: * {@link #VISIBLE} or {@link #INVISIBLE}. */ protected void onDisplayHint(int hint) { } #具体优化工作1.进入推荐页时,只加载Scrollview中可见的图片 1234567891011121314151617181920212223@Override public void onResume() { super.onResume(); Logger.getLogger().d("onResume"); if (getUserVisibleHint()) { setScrollVisibleView(); } } private void setScrollVisibleView() { if (mRecommendContainerLayout == null) { return; } for (int i = 0; i < mRecommendContainerLayout.getChildCount(); i++) { final RecommendContainer recommendContainer = (RecommendContainer) mRecommendContainerLayout.getChildAt(i); if (isVisibleInScrollView(mScrollView, recommendContainer)) { Logger.getLogger().d("setScrollVisibleView v=%s,vi=%s", recommendContainer, View.VISIBLE); recommendContainer.dispatchDisplayHint(View.VISIBLE); } else { //Logger.getLogger().d("setScrollVisibleView v=%s,vi=%s", recommendContainer, View.GONE); //recommendContainer.dispatchDisplayHint(View.INVISIBLE); } } } 2.离开推荐页时,释放Scrollview中不可见的图片1234567891011121314151617@Overridepublic void setUserVisibleHint(final boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); Logger.getLogger().d("setUserVisibleHint, isVisibleToUser=%s", isVisibleToUser); if (mRecommendContainerLayout == null) { return; } for (int i = 0; i < mRecommendContainerLayout.getChildCount(); i++) { final RecommendContainer recommendContainer = (RecommendContainer) mRecommendContainerLayout.getChildAt(i); final boolean isVisibleInScrollView = isVisibleInScrollView(mScrollView, recommendContainer); Logger.getLogger().d("setUserVisibleHint v=%s,isVisibleToUser=%s,isVisibleInScrollView=%s," + "checkIsVisible=%s", recommendContainer.getId(), isVisibleToUser, isVisibleInScrollView, ViewUtils.checkIsVisible(getContext(), recommendContainer)); recommendContainer.dispatchDisplayHint( isVisibleInScrollView ? View.VISIBLE : View.GONE); }} 3.点击图片进入详情页后,释放全部图片123456789101112131415161718192021@Overridepublic void onPause() { super.onPause(); Logger.getLogger().d("onPause"); hideAllViews();}private void hideAllViews() { if (mRecommendContainerLayout == null) { return; } for (int i = 0; i < mRecommendContainerLayout.getChildCount(); i++) { final RecommendContainer recommendContainer = (RecommendContainer) mRecommendContainerLayout.getChildAt(i); Logger.getLogger().d("hideAllViews v=%s,vi=%s", recommendContainer, View.GONE); mRecommendContainerLayout.postDelayed(new Runnable() { @Override public void run() { recommendContainer.dispatchDisplayHint(View.INVISIBLE); } }, 300); }} 4.Scrollview滚动时只加载可见的图片1234567@Overridepublic void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy) { if (Math.abs(oldy - y) > 50) { //Logger.getLogger().d("recommendFragment setScrollVisibleView"); setScrollVisibleView(); }} #参考关于fragment到底是否可见的问题如何判断Fragment是否对用户可见Android: how to check if a View inside of ScrollView is visible?]]></content>
<categories>
<category>技术</category>
</categories>
<tags>
<tag>Android</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hello World]]></title>
<url>%2F2019%2F01%2F19%2Fhello-world%2F</url>
<content type="text"><![CDATA[Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new "My New Post" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment]]></content>
</entry>
</search>