设为首页 加入收藏

TOP

Android 开发你需要了解的那些事(二)
2019-08-24 00:10:53 】 浏览:47
Tags:Android 开发 需要 了解 那些
到耗时任务,就很潇洒的一个 new Thread 全部搞定。

如果你当前界面只有一个耗时任务,而且只需要调用一次,那么你进入该界面用 new Thread 来处理没有问题。

但是假设像上面我们描述的场景那样,需要调用多次的时候。你就不能简单粗暴的使用 new Thread 了。

推荐方式是使用线程池。
一个原因是避免一些厂商的线程数目限制。
另一个原因是减少线程的频繁创建和销毁。

第三点:内部类都可能存在的问题

Q: 上面我们说到了,如果界面调用一次,而且需要启动线程的时候。可以使用 new Thread 创建,那么直接使用 new Thread 可能还有什么问题吗?

这里想考察的点可能比较晦涩一点。

由于内部类会持有外部类的引用。假设在 Activity 里面通过匿名内部类的方式来启动线程做耗时任务。当用户退出界面时,由于内部类还持有 Activity 的引用,因此 Activity 没法得到释放。

就会存在内存泄漏问题。

解决方法也比较统一,那就是将内部类改为静态内部类。

所以修改后的代码对比如下:

修改前:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                //TODO
            }
        }).start();
    }
}

修改后:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new StaticThread().start();
    }

    private static class StaticThread extends Thread {
        @Override
        public void run() {
            super.run();
            //TODO
        }
    }
}

第四点:弱引用场景应用

Q: 用过 Handler 吗?

A: 用过。

Q: 写一下简单的 demo 我看下。

这个是紧接第三点。如果不涉及界面交互,只需要使用到静态内部类就可以解决。但是当 Handler 里面需要做界面更新处理时,那么需要使用弱引用。因为静态内部类的处理方式本来就是为了避免 Activity 无法得到释放。你如果把 Activity 直接传进来,那么 Activity 的引用被静态内部类持用了,所以这个时候就需要使用到弱引用了。

直接上代码:

public class MainActivity extends AppCompatActivity {
    private static class StaticHandler extends Handler {
        private WeakReference<MainActivity> activityWeakReference;

        public StaticHandler(MainActivity mainActivity) {
            this.activityWeakReference = new WeakReference<>(mainActivity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //TODO
            //use activityWeakReference.get() to get view
        }
    }

    private StaticHandler mStaticHandler = new StaticHandler(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mStaticHandler.sendEmptyMessage(0);
    }
}

第五点:持久化 SharedPreferences 的使用

一般很多网上教程和例子在 SharedPreferences 的数据写入时,一般都会使用 Editor 的 commit 方法。

由于 commit 方法是同步写入的。并且写文件属于 I/O 操作,如果你有大量的数据需要写入,并且你是在主线程处理的,可能会导致流畅性受影响。极端情况下可能会出现 ANR。

我们点进去源码看下:

If you don't care about the return value and you're using this from your application's main thread, consider using {@link #apply} instead.

其实源码也说的很清楚了。如果你不关心返回值并且你是在应用的主线程使用的话,考虑使用 apply 替换 commit。

由于我们一般不会处理返回值,因此建议使用 apply 替换 commit。

apply 会把变化马上写进内存,然后通过异步方式去写入。

Unlike {@link #commit}, which writes its preferences out to persistent storage synchronously, {@link #apply} commits its changes to the in-memory {@link SharedPreferences} immediately but starts an asynchronous commit to disk and you won't be notified of any failures.

当然源码还有一个注释如下:

If another editor on this {@link SharedPreferences} does a regular {@link #commit} while a {@link #apply} is still outstanding, the {@link #commit} will block until all async commits are completed as well as the commit itself.

大概意思就是 apply 如果在处理中还未完成的情况下,commit 会阻塞直到所有异步操作完成才会去 commit。

因此如果要替换,建议将 commit 都替换为 apply。

第六点:数据库相关处理

这里主要是考虑类似微信 IM 登录后拉取大量离线消息写入数据库的问题。

通过对比开启事务和不开启事务的耗时来进行说明。

比如不开启事务插入 10000 条纪录和开启事务插入 10000 条纪录耗时对比。

对于大量的数据库操作,建议开启事务的方式,速度的提升是很明显的。

参考链接:
Android ANR:原理分析及解决办法

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Xamarin学习(一)---- 环境准备 下一篇Android8.1源码编译实践(Mac)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目