Android异步处理

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/wangwei708846696/article/details/80793293

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<ProcessState> 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:<pid>_x
        String8 name = makeBinderThreadName();
        //isMain=true
        sp<Thread> 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() {
}

@Override
public 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<ContentResolver>(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做处理

@Override
public void onCreate() {
    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

@Override
public 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,后面我会专门详解,掌握了这两个基石很多困惑会迎刃而解。

猜你喜欢

转载自blog.csdn.net/wangwei708846696/article/details/80793293