Android开发常用技巧

APP 0 1003
00224176
00224176 版主 - APP 关注 2021年7月22日 15:51 编辑
<p><span style="color: rgb(77, 77, 77); font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-size: 16px;">1.Context的用法&nbsp;</span><br></p><p><span style="color: rgb(77, 77, 77); font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-size: 16px;">举例:单利模式(非线程安全)</span><span style="color: rgb(77, 77, 77); font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-size: 16px;"><br></span></p><pre><code>public class Singleton {<br> private static Singleton instance;<br> private Context mContext;<br> <br> private Singleton(Context context) {<br> this.mContext = context;<br> }<br> <br> public static Singleton getInstance(Context context) {<br> if (instance == null) {<br> instance = new Singleton(context);<br> }<br> return instance;<br> }<br>}</code></pre><p>这是一个非线程安全的单例模式,instance作为静态对象,其生命周期要长于普通的对象,其中也包含Activity,假如Activity A去getInstance获得instance对象,传入this,常驻内存的Singleton保存了你传入的Activity A对象,并一直持有,即使Activity被销毁掉,但因为它的引用还存在于一个Singleton中,就不可能被GC掉,这样就导致了内存泄漏。<br><br>注意事项:<br><br>一般Context造成的内存泄漏,几乎都是当Context销毁的时候,却因为被引用导致销毁失败,而Application的Context对象可以理解为随着进程存在的,所以我们总结出使用Context的正确姿势:<br>1:当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。<br>2:不要让生命周期长于Activity的对象持有到Activity的引用。<br>3:尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。<br><br>2.Class加载过程之自定义ClassLoader</p><pre><code>/**<br> * 自定义文件类加载器<br> */<br>public class FileSystemClassLoader extends ClassLoader {<br> <br> private String rootDir;<br> <br> public FileSystemClassLoader(String rootDir){<br> this.rootDir = rootDir;<br> }<br> <br> @Override<br> protected Class&lt;?&gt; findClass(String name) throws ClassNotFoundException {<br> Class&lt;?&gt; loadedClass = findLoadedClass(name);<br> if(null != loadedClass){<br> return loadedClass;<br> }else{<br> ClassLoader classLoader = this.getParent();<br> try{<br> loadedClass = classLoader.loadClass(name);<br> }catch (ClassNotFoundException e){<br> e.printStackTrace();<br> }<br> if(null != loadedClass){<br> return loadedClass;<br> }else{<br> byte[] classData = getClassData(name);<br> if(classData == null){<br> throw new ClassNotFoundException();<br> }else {<br> loadedClass = defineClass(name,classData,0,classData.length);<br> }<br> }<br> }<br> return loadedClass;<br> }<br> <br> private byte[] getClassData(String name){<br> String path = rootDir+"/"+name.replace('.','/')+".class";<br> InputStream is = null;<br> ByteArrayOutputStream baos = new ByteArrayOutputStream();<br> <br> try {<br> is = new FileInputStream(path);<br> byte[] bytes = new byte[1024];<br> int temp = 0;<br> while ((temp = is.read(bytes)) != -1){<br> baos.write(bytes,0,temp);<br> }<br> return baos.toByteArray();<br> } catch (IOException e) {<br> e.printStackTrace();<br> return null;<br> } finally {<br> try {<br> if(baos != null){<br> baos.close();<br> }<br> if(is != null){<br> is.close();<br> }<br> } catch (IOException e) {<br> e.printStackTrace();<br> }<br> }<br> }<br>}</code></pre><p>definclass()<br><br>把字节码转化为Class<br><br>findClass()<br><br>根据名称或位置加载.class字节码,然后使用defineClass<br>通常由子类去实现<br>loadClass()<br><br>findLoadedClass(String) 调用这个方法,查看这个Class是否已经别加载<br><br>如果没有被加载,继续往下走,查看父类加载器,递归调用loadClass()<br><br>如果父类加载器是null,说明是启动类加载器,查找对应的Class<br><br>如果都没有找到,就调用findClass(String)</p>
赞(0) 收藏(0)  分享
相关标签:
0个回复
  • 消灭零回复
Vaptcha启动中...