| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
Trinidad36M
7年前发布

记一场 Android 技术答疑

   <p>之前在Stuq的Android课程中有幸分享了一些关于优化的问题,后期又处理了一些来自网友的问题,这里简单以文字形式做个整理.</p>    <h2><strong>网络IO应该在哪种形式的线程中执行</strong></h2>    <ul>     <li> <p>首先网络IO一般耗时比较长,有的可能到几十毫秒</p> </li>     <li> <p>由于耗时较长,如果采用单一线程处理,势必导致后续的请求无法快速执行</p> </li>     <li> <p>建议使用线程池来处理达到快速响应和线程的复用。</p> </li>    </ul>    <p>简单示例:</p>    <pre>  <code class="language-java">private void testDoNetworkRequest() {      int corePoolSize = 5;      int maxPoolSize = 10;      //线程数量超过核心线程数之后的超时时间,即超过这个时间还没有新的task,多余的线程则销毁掉。      long keepAliveTime = 10;      ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());        executor.execute(new Runnable() {          @Override          public void run() {              //Do network IO here          }      });  }</code></pre>    <h2><strong>如何优化字符串拼接</strong></h2>    <ul>     <li> <p>字符串拼接无法避免的创建StringBuilder对象</p> </li>     <li> <p>如果是循环情况下拼接,需要显式在循环外声明一个StringBuilder对象</p> </li>    </ul>    <h3><strong>不好的代码</strong></h3>    <pre>  <code class="language-java">public void  implicitUseStringBuilder(String[] values) {    String result = "";    for (int i = 0 ; i < values.length; i ++) {        result += values[i];//create new StringBuilder object every time    }    System.out.println(result);  }</code></pre>    <h3><strong>改进后的代码</strong></h3>    <pre>  <code class="language-java">public void explicitUseStringBuider(String[] values) {    StringBuilder result = new StringBuilder();    for (int i = 0; i < values.length; i ++) {        result.append(values[i]);    }  }</code></pre>    <h2><strong>使用Handler到底需不需要使用弱引用,什么时候情况下用</strong></h2>    <ul>     <li> <p>正常境况下的引用都为强引用,其特点是及时内存溢出也不可以被回收</p> </li>    </ul>    <pre>  <code class="language-java">ArrayList list = new ArrayList();</code></pre>    <ul>     <li> <p>弱引用则会在垃圾回收时被回收掉,因而弱引用解决内存泄露的一种方法。</p> </li>    </ul>    <pre>  <code class="language-java">ArrayList list = new ArrayList();  WeakReference<ArrayList> listWeakRef = new WeakReference<ArrayList>(list);  ArrayList myList = listWeakRef.get();</code></pre>    <ul>     <li> <p>Handler是否需要设置弱引用,取决于它是否可能发生内存泄露</p> </li>    </ul>    <h3><strong>Handler内存泄露的场景</strong></h3>    <ul>     <li>Message的target变量实际是Handler对象</li>     <li>Message存放在MessageQueue中</li>     <li>MessageQueue通常为Looper持有</li>     <li>Looper和可以认为和线程生命周期相同</li>     <li>通常情况下,我们使用匿名内部类的形式创建Handler,而匿名内部类(非静态内部类)会隐式持有外部类的引用。即如下的mHandler会隐式持有Activity的实例引用。</li>    </ul>    <pre>  <code class="language-java">private Handler mHandler = new Handler() {      @Override      public void handleMessage(Message msg) {          super.handleMessage(msg);      }  };</code></pre>    <ul>     <li> <p>如果有一个延迟很久的消息,可能会导致Activity内存泄露</p> </li>     <li> <p>可以使用弱引用解决内存泄露问题</p> </li>     <li> <p>也可以在Activity onDestory方法中调用handler.removeCallbacksAndMessages(null);</p> </li>    </ul>    <h2><strong>网络数据返回先通知界面还是先更新数据库</strong></h2>    <ul>     <li>通常境况下,可以选择先更新界面再更新数据库</li>     <li>如果数据很重要,建议先更新数据库在通知界面更新</li>    </ul>    <h2><strong>业务场景:需要定时后台扫描数据库,上传本地照片至云端,定时任务采用何种模式</strong></h2>    <ul>     <li> <p>Handler或者Timer定时一般为秒级别的任务,Timer会启动额外线程,而Handler可以不用。</p> </li>     <li> <p>无论是Handler还是Timer都需要依赖于进程存活</p> </li>     <li> <p>利用Handler实现定时任务的类: HandlerTimer</p> </li>     <li> <p>如果时间较长,则需要使用AlarmManager</p> </li>     <li> <p>另外,我们对于这种业务应该优先考虑是否可以基于事件通知。</p> </li>     <li> <p>如果是加入媒体库的文件,我们可以使用registerContentObserver监听媒体库文件变化。</p> </li>    </ul>    <h2><strong>static 单例是怎么保证单例的?没太看明白</strong></h2>    <ul>     <li> <p>static变量为类所有</p> </li>     <li> <p>staitc只初始化一次,即在调用的时候。</p> </li>     <li> <p>如下代码,STATIC_OBJECT只在第一次调用时初始化,后续调用则不会再执行初始化</p> </li>    </ul>    <pre>  <code class="language-java">public class Example {      public static Object STATIC_OBJECT = new Object();  }</code></pre>    <ul>     <li>使用static机制创建单例</li>    </ul>    <pre>  <code class="language-java">public class SingleInstance {      private SingleInstance() {      }        public static SingleInstance getInstance() {          return SingleInstanceHolder.sInstance;      }        private static class SingleInstanceHolder {          private static SingleInstance sInstance = new SingleInstance();      }  }</code></pre>    <h2><strong>把Activity作为参数传给一个静态方法,会影响这个Activity的正常销毁吗</strong></h2>    <ul>     <li> <p>内存泄露与方法是否是静态与否无关,与内部的方法体实现有关系。</p> </li>     <li> <p>内存泄露可以简单理解成:生命周期长的对象不正确持有了持有了生命周期短的对象,导致生命周期短的对象无法回收。</p> </li>     <li> <p>比如Activity实例被Application对象持有,Activity实例被静态变量持有。</p> </li>    </ul>    <h2><strong>Bitmap优化</strong></h2>    <ul>     <li> <p>options.inJustDecodeBounds = true;可以获取width,height和mimetype等信息,但不会申请内存占用</p> </li>     <li> <p>合理进行缩放,一个高分辨率的图片不仅展示在一个小的imageView中,不仅不会有任何视觉优势,反而还占用了很大的内存</p> </li>     <li> <p>将Bitmap处理移除主线程</p> </li>     <li> <p>使用LruCache或者DiskLruCache缓存Bitmap</p> </li>     <li> <p>before 2.3 手动调用recycle()方法</p> </li>    </ul>    <p>多次在生产签名打包后的apk,出现功能不可用的情况,比方说有个社会化分享功能,写代码时都可以正常实现,但签名生成apk后该功能无法再使用了,点击分享面板的平台,没有任何响应。请问是怎么回事,这种问题解决应该从哪几个方面入手,希望有一些思路可供参考</p>    <ul>     <li> <p>应该是混淆引起的</p> </li>     <li> <p>混淆是将易读性较好的变量,方法和类名替换成可读性较差的名称</p> </li>     <li> <p>混淆的目的是为了加大逆向的成本,但不能避免</p> </li>     <li> <p>通常混淆的处理是将某些库不加入混淆</p> </li>     <li> <p>第三方的库不建议混淆</p> </li>    </ul>    <h3><strong>一些需要排除混淆的</strong></h3>    <ul>     <li> <p>被native方法调用的java方法</p> </li>     <li> <p>供javascript调用的java方法</p> </li>     <li> <p>反射调用的方法</p> </li>     <li> <p>AndroidManifest中声明的组件</p> </li>     <li> <p>总结:即所有硬编码的元素(变量,方法,类)</p> </li>    </ul>    <p> </p>    <p> </p>    <p>来自:http://www.udpwork.com/item/15888.html</p>    <p> </p>    
 本文由用户 Trinidad36M 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
 转载本站原创文章,请注明出处,并保留原始链接、图片水印。
 本站是一个以用户分享为主的开源技术平台,欢迎各类分享!
 本文地址:https://www.open-open.com/lib/view/open1477363147690.html
数据库 安卓开发 Android开发 移动开发