Android异步处理

大家好,我叫王菜鸟,今天给大家分享的内容是Android中异步的处理。那下面我们就从几个方面开始介绍Android中的异步操作。

  1. 什么是同步,什么是异步。
  2. 为什么要异步?
  3. Android中异步有哪些?对应这些异步操作的原理是什么?
  4. 如何进行异步操作?
什么是同步,什么是异步?

同步,异步可以理解成是形容词,修饰一次方法的调用,同步方法一旦开始,调用者必须等到方法调用返回后才进行后面的一系列操作。异步方法调用,则比较类似一次消息的发送,一旦开始就会立即返回,调用者此时不用等待被调用的操作执行完成才继续执行,而是继续处理调用者后续的操作。

为什么要异步?

我们要清楚为什么异步,那就得知道什么是并行什么是并发。并行的多个任务是同时执行的,但是对于并发来讲这个过程只是不断交换的过程。怎么理解这两个过程,比如说我们在调节婆媳关系的时候,我们一定是跑到妈那里说媳妇好话,然后屁颠屁颠跑到媳妇那里说妈也是为了咱们好。跑来跑去这个过程就叫做并发,因为对于这个整体而言你和妈沟通好了,你也和媳妇沟通好了,通过不断地交替完成了一个结果。那什么是并行呢?你不太会说话,你就想出来把村长叫来,村长和你妈沟通,你和你媳妇沟通最后结果还是和解婆媳关系。这就叫做并发。

那么在pc中怎么理解,如果pc是单核的那就谈不上并行,因为没有村长。只能靠自己和解。那如果pc是多核那就谈得上并行,可以叫上村长,如果更多核可以连村长媳妇都叫来都没问题。

如果把村长媳妇叫来,那可能存在隐患,比如你看上人家村长媳妇了,矛盾更大了,最后体现关系缓和不了,这就叫做死锁。因为你看上村长媳妇村长看上你媳妇。但是由于道德约束和法律约束,不能互换。但是喜欢就是喜欢永不放弃,这就产生了死锁。

回归我们说的为什么要异步,放入pc中看,多核可以并行那就省去了你的不少事情,就相当于因为把一半的事情都交给村长了。所以效率会更好。计算机中也一样多个线程计算效率会更高。所以提高运算效率就是异步的,目的。

Android中异步有哪些操作,对应这些操作原理是什么?

首先我们作为在Android概念区别的的角度而言,Android中核心的可以划分成
- 主线程
- Binder线程
- 后台线程
当然如果您要说,主线程Binder线程等在Linux上都是启动一个线程那您理解的虽然正确,但是没有在笔者说的这个角度出发看。

主线程

需要明确的是,我们经常说的ActivityThread是主线程,这句话不准确。ActivityThread并没有继承Thread类,他只是负责应用进程中一些核心的操作,所以他严格意义上不是进程。Zygote把进程fork()出来之后,得做一些Android应用层面的初始化工作,在这个过程中会启动一套Handler机制我们将这个称之为主线程,其中的MessageQueue称之为主消息队列。其源码为:

SystemServer.run()

private void run() {    ...    Looper.prepareMainLooper();//主线程looper    //加载android_servers.so库在frameworks/base/services/目录    System.loadLibrary("android_servers");    ...    createSystemContext(); //初始化系统上下文    //创建系统服务管理    mSystemServiceManager = new SystemServiceManager(mSystemContext);    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);    try {        startBootstrapServices(); // 引导服务        startCoreServices();      // 核心服务        startOtherServices();     // 其他服务    } catch (Throwable ex) {        Slog.e("System", "************ Failure starting system services", ex);        throw ex;    }    //一直loop    Looper.loop();    throw new RuntimeException("Main thread loop unexpectedly exited");}

这也就是我们其实在最开始的线程里面启动了一套Handler机制。只不过谷歌把UI操作都让这个loop处理。所以我们贴切的称之为主线程。

Binder线程

Binder线程是进行Binder机制通信的线程,也就是Android中的跨进程通信。
Binder线程如果我们是应用开发者很难感知的到Binder线程的存在,因为他是在native层创建的,我们看下源码,这部分其实作为了解,深入也没有太大意义,有兴趣的同学可以跟随笔者角度。没兴趣的忽略binder线程继续向下看哈。

还在Zygote中,当应用层需要启动一个进程时候(调用Process.start()方法)向Zygote发送socket消息,最后执行到app_main.cpp中的onZygoteInit。

app_main.cpp中的onZygoteInit()

virtual void onZygoteInit() {    sp proc = ProcessState::self();    //启动新binder线程    proc->startThreadPool();}

继续看看如何启动线程池

void ProcessState::startThreadPool(){    AutoMutex _l(mLock);    //Linux中多线程同步,俗称加锁    if (!mThreadPoolStarted) {        mThreadPoolStarted = true;        spawnPooledThread(true);    }}

追踪spawnPooledThread方法

void ProcessState::spawnPooledThread(bool isMain){    if (mThreadPoolStarted) {        //获取Binder线程名,此时命名规则Binder:_x        String8 name = makeBinderThreadName();        //isMain=true        sp t = new PoolThread(isMain);        t->run(name.string());    }}

这个时候mIsMain=true,通过名称判断joinThreadPool加入线程池

class PoolThread : public Thread{public:    PoolThread(bool isMain)        : mIsMain(isMain)    {    }protected:    virtual bool threadLoop()  {        IPCThreadState::self()->joinThreadPool(mIsMain);//此时true        return false;    }    const bool mIsMain;};
void IPCThreadState::joinThreadPool(bool isMain){    //创建Binder线程(isMain代表主线程信号)    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);    set_sched_policy(mMyThreadId, SP_FOREGROUND); //设置前台调度策略    status_t result;    do {        processPendingDerefs(); //清除队列的引用        result = getAndExecuteCommand(); //处理与Binder交互和binder响应的操作        ...    } while (result != -ECONNREFUSED && result != -EBADF);    mOut.writeInt32(BC_EXIT_LOOPER);  // 线程退出循环    ...}

也就是在getAndExecuteCommand()这个过程会和Linux底层打交道将BC_ENTER_LOOPER交给底层识别

后台线程

我们在代码里面new Thread()这个就叫做后台进程

我们这里并没有继承关系,或者组合关系等,我们只是说常见的一些用到的类,后面我们说这些类分别有什么作用

  • Thread
  • HandlerThread
  • Executor
  • AsyncQueryHandler
  • IntentService
  • AsyncTask

Thread

针对Thread我们都知道继承实现run方法,或者把一个Runnable接口给Thread。

class MyThread extends Thread{    @Override    public void run() {    }}
Thread thread = new Thread(new Runnable() {    @Override    public void run() {    }});

我们还知道只要不调用Thread的start()方法,就没有开启一个线程,Thread就相当于还是一个普通类。

HandlerThread

HandlerThread是一个集成了Looper,MessageQueue的线程。在其run方法中会调用Looper.prepare()方法,我们看代码吧。

HandlerThread.java

//Call back method that can be explicitly overridden if needed to execute some setup before Looper loops.protected void onLooperPrepared() {}@Overridepublic void run() {    mTid = Process.myTid();    Looper.prepare();//启动一套Handler机制    synchronized (this) {        mLooper = Looper.myLooper();        notifyAll();    }    Process.setThreadPriority(mPriority);//设置线程策略    onLooperPrepared();    Looper.loop();    mTid = -1;}

很显然我们如果需要做一些事情就放入onLooperPrepared()方法中

AsyncQueryHandler

对于这个,构造中创建了一个HandlerThread自己内部实现了一个Handler叫做WorkerHandler类,这个类封装了对ContentProvider的一些操作。原理一样,大概浏览下代码

HandlerThread.java

public AsyncQueryHandler(ContentResolver cr) {    super();    mResolver = new WeakReference(cr);    synchronized (AsyncQueryHandler.class) {        if (sLooper == null) {            HandlerThread thread = new HandlerThread("AsyncQueryWorker");//是的吧            thread.start();            sLooper = thread.getLooper();        }    }    mWorkerThreadHandler = createHandler(sLooper);}protected Handler createHandler(Looper looper) {    return new WorkerHandler(looper);}

Excutor

public interface Executor {    void execute(Runnable command);}

这个只是一个接口。后面和AsyncTask结合那就发挥更大的作用了

IntentService.java

在内部实现了HandlerThread自己实现了Handler叫做ServiceHandler做处理

@Overridepublic void onCreate() {    super.onCreate();    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");    thread.start();    mServiceLooper = thread.getLooper();    mServiceHandler = new ServiceHandler(mServiceLooper);}@Overridepublic void onStart(@Nullable Intent intent, int startId) {    Message msg = mServiceHandler.obtainMessage();    msg.arg1 = startId;    msg.obj = intent;    mServiceHandler.sendMessage(msg);}

做的处理是:

private final class ServiceHandler extends Handler {    public ServiceHandler(Looper looper) {        super(looper);    }    @Override    public void handleMessage(Message msg) {        onHandleIntent((Intent)msg.obj);//是个abstract方法        stopSelf(msg.arg1);    }}

原理一样,都是HandlerThread的应用。

如何进行异步操作?

就是利用我们上面说的那些进行异步,只不过我要单独提出来Handler机制和AsyncTask,后面我会专门详解,掌握了这两个基石很多困惑会迎刃而解。

更多相关文章

  1. Google Android操作系统内核编译图文教程
  2. Google Android操作系统内核编译图文教程
  3. Android的内存机制
  4. [Android] AsyncTask详解
  5. Google Android操作系统内核编译图文教程
  6. Android中的消息机制
  7. Android(安卓)进度暂停和继续
  8. Chronometer android计时器组件Chronometer的使用,android通话时
  9. Android(安卓)文件操作

随机推荐

  1. Android3D游戏开发系列(2)色彩渲染和旋转
  2. Android高效率编码-细节,控件,架包,功能,工具
  3. FrameLayout 自定义字母导航条 android:l
  4. 开发5年,在资本寒冬下的 android开发者,该
  5. 做iOS开发程序员10个必需的开发工具和资
  6. Android(安卓)sqlite数据库操作通用框架A
  7. Android(安卓)网络连接——ConnectivityM
  8. Android高级工程师BAT面试题及知识点整理
  9. Android(安卓)主流开源框架(七)Glide 的缓
  10. 学android一定要会Java吗