记一场 Android 技术答疑

之前在Stuq的Android课程中有幸分享了一些关于优化的问题,后期又处理了一些来自网友的问题,这里简单以文字形式做个整理.

网络IO应该在哪种形式的线程中执行

  • 首先网络IO一般耗时比较长,有的可能到几十毫秒
  • 由于耗时较长,如果采用单一线程处理,势必导致后续的请求无法快速执行
  • 建议使用线程池来处理达到快速响应和线程的复用。

简单示例:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

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 } }); }

关于线程的文章,请参考

如何优化字符串拼接

  • 字符串拼接无法避免的创建StringBuilder对象
  • 如果是循环情况下拼接,需要显式在循环外声明一个StringBuilder对象

不好的代码

1 2 3 4 5 6 7

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); }

改进后的代码

1 2 3 4 5 6

public void explicitUseStringBuider(String[] values) { StringBuilder result = new StringBuilder(); for (int i = 0; i < values.length; i ++) { result.append(values[i]); } }

关于拼接字符串的文章

使用Handler到底需不需要使用弱引用,什么时候情况下用

  • 正常境况下的引用都为强引用,其特点是及时内存溢出也不可以被回收

1

ArrayList list = new ArrayList();

  • 弱引用则会在垃圾回收时被回收掉,因而弱引用解决内存泄露的一种方法。

1 2 3

ArrayList list = new ArrayList(); WeakReference<ArrayList> listWeakRef = new WeakReference<ArrayList>(list); ArrayList myList = listWeakRef.get();

  • Handler是否需要设置弱引用,取决于它是否可能发生内存泄露

Handler内存泄露的场景

  • Message的target变量实际是Handler对象
  • Message存放在MessageQueue中
  • MessageQueue通常为Looper持有
  • Looper和可以认为和线程生命周期相同
  • 通常情况下,我们使用匿名内部类的形式创建Handler,而匿名内部类(非静态内部类)会隐式持有外部类的引用。即如下的mHandler会隐式持有Activity的实例引用。

1 2 3 4 5 6

private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); } };

  • 如果有一个延迟很久的消息,可能会导致Activity内存泄露
  • 可以使用弱引用解决内存泄露问题
  • 也可以在Activity onDestory方法中调用handler.removeCallbacksAndMessages(null);

相关文章

网络数据返回先通知界面还是先更新数据库

  • 通常境况下,可以选择先更新界面再更新数据库
  • 如果数据很重要,建议先更新数据库在通知界面更新

业务场景:需要定时后台扫描数据库,上传本地照片至云端,定时任务采用何种模式

  • Handler或者Timer定时一般为秒级别的任务,Timer会启动额外线程,而Handler可以不用。
  • 无论是Handler还是Timer都需要依赖于进程存活
  • 利用Handler实现定时任务的类:HandlerTimer
  • 如果时间较长,则需要使用AlarmManager
  • 另外,我们对于这种业务应该优先考虑是否可以基于事件通知。
  • 如果是加入媒体库的文件,我们可以使用registerContentObserver监听媒体库文件变化。

static 单例是怎么保证单例的?没太看明白

  • static变量为类所有
  • staitc只初始化一次,即在调用的时候。
  • 如下代码,STATIC_OBJECT只在第一次调用时初始化,后续调用则不会再执行初始化

1 2 3

public class Example { public static Object STATIC_OBJECT = new Object(); }

  • 使用static机制创建单例

1 2 3 4 5 6 7 8 9 10 11 12

public class SingleInstance { private SingleInstance() { } public static SingleInstance getInstance() { return SingleInstanceHolder.sInstance; } private static class SingleInstanceHolder { private static SingleInstance sInstance = new SingleInstance(); } }

关于单例的文章

把Activity作为参数传给一个静态方法,会影响这个Activity的正常销毁吗

  • 内存泄露与方法是否是静态与否无关,与内部的方法体实现有关系。
  • 内存泄露可以简单理解成:生命周期长的对象不正确持有了持有了生命周期短的对象,导致生命周期短的对象无法回收。
  • 比如Activity实例被Application对象持有,Activity实例被静态变量持有。

关于Android中内存泄漏的文章

Bitmap优化

  • options.inJustDecodeBounds = true;可以获取width,height和mimetype等信息,但不会申请内存占用
  • 合理进行缩放,一个高分辨率的图片不仅展示在一个小的imageView中,不仅不会有任何视觉优势,反而还占用了很大的内存
  • 将Bitmap处理移除主线程
  • 使用LruCache或者DiskLruCache缓存Bitmap
  • before 2.3 手动调用recycle()方法

关于Bitmap的文章

多次在生产签名打包后的apk,出现功能不可用的情况,比方说有个社会化分享功能,写代码时都可以正常实现,但签名生成apk后该功能无法再使用了,点击分享面板的平台,没有任何响应。请问是怎么回事,这种问题解决应该从哪几个方面入手,希望有一些思路可供参考

  • 应该是混淆引起的
  • 混淆是将易读性较好的变量,方法和类名替换成可读性较差的名称
  • 混淆的目的是为了加大逆向的成本,但不能避免
  • 通常混淆的处理是将某些库不加入混淆
  • 第三方的库不建议混淆

一些需要排除混淆的

  • 被native方法调用的java方法
  • 供javascript调用的java方法
  • 反射调用的方法
  • AndroidManifest中声明的组件
  • 总结:即所有硬编码的元素(变量,方法,类)

关于混淆,请参考文章读懂 Android 中的代码混淆

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏熊二哥

快速入门系列--MVC--05行为

    Action执行包含内容比较多,主要有同步/异步Action的概念和执行过程,Authorationfilter, ActionFiltor, Resu...

20570
来自专栏Rindew的iOS技术分享

苏宁一面

19040
来自专栏熊二哥

快速入门系列--WebAPI--04在老版本MVC4下的调整

WebAPI是建立在MVC和WCF的基础上的,原来微软老是喜欢封装的很多,这次终于愿意将http编程模型的相关细节暴露给我们了。在之前的介绍中,基本上都基于.N...

25260
来自专栏谦谦君子修罗刀

RN与原生通讯(安卓篇)一、RN调用安卓代码(简单)二、RN用消息机制方式与安卓原生代码切换三、RN用Promise机制与安卓原生代码通信四、RN用callback回调方式与安卓原生代码通信

明天和意外你永远都不知道哪一个先来,编程界亦是如此。例如某个已经有原生代码开发模块的项目要求用RN扩张某些功能;又例如,RN中未封装到的组件非得求助于原生代码。...

40470
来自专栏向治洪

Android面试之高级篇

结合自己之前去很多大公司的面试经历和自己面别人的一些题,这里做一些总结,Android面试中常见的面试题。 1,Android的Handler运行机制     ...

32390
来自专栏源哥的专栏

基于linux的嵌入IPv4协议栈的内容过滤防火墙系统(5)-包过滤模块和内容过滤模块所采用的各种技术详述

3。1 module编程 module可以说是 Linux 的一大革新。有了 module 之后,写 device driver 不再是一项恶梦,修改 ker...

14030
来自专栏码匠的流水账

聊聊hikari连接池的idleTimeout及minimumIdle属性

本文主要研究一个hikari连接池的idleTimeout及minimumIdle属性

47810
来自专栏james大数据架构

MVC中局部视图的使用

加载部分视图 $("#result").load("/home/message",function(){ //加载完之后隐藏进度条 });  public Ac...

21970
来自专栏技术小讲堂

ASP.NET AJAX(1)__Microsoft AJAX LibraryASP.NET AJAX(1)__Microsoft AJAX Library

ASP.NET AJAX(1)__Microsoft AJAX Library Microsoft AJAX Library为我们提供的客户端框架,提供的内容大...

30840
来自专栏Java面试通关手册

面试必备之深入理解自旋锁

分享一个我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Sn...

76430

扫码关注云+社区

领取腾讯云代金券