Android异步处理
Android异步处理
大家好,我叫王菜鸟,今天给大家分享的内容是Android中异步的处理。那下面我们就从几个方面开始介绍Android中的异步操作。
- 什么是同步,什么是异步。
- 为什么要异步?
- Android中异步有哪些?对应这些异步操作的原理是什么?
- 如何进行异步操作?
什么是同步,什么是异步?
同步,异步可以理解成是形容词,修饰一次方法的调用,同步方法一旦开始,调用者必须等到方法调用返回后才进行后面的一系列操作。异步方法调用,则比较类似一次消息的发送,一旦开始就会立即返回,调用者此时不用等待被调用的操作执行完成才继续执行,而是继续处理调用者后续的操作。
为什么要异步?
我们要清楚为什么异步,那就得知道什么是并行什么是并发。并行的多个任务是同时执行的,但是对于并发来讲这个过程只是不断交换的过程。怎么理解这两个过程,比如说我们在调节婆媳关系的时候,我们一定是跑到妈那里说媳妇好话,然后屁颠屁颠跑到媳妇那里说妈也是为了咱们好。跑来跑去这个过程就叫做并发,因为对于这个整体而言你和妈沟通好了,你也和媳妇沟通好了,通过不断地交替完成了一个结果。那什么是并行呢?你不太会说话,你就想出来把村长叫来,村长和你妈沟通,你和你媳妇沟通最后结果还是和解婆媳关系。这就叫做并发。
那么在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,后面我会专门详解,掌握了这两个基石很多困惑会迎刃而解。
更多相关文章
- Google Android操作系统内核编译图文教程
- Google Android操作系统内核编译图文教程
- Android的内存机制
- [Android] AsyncTask详解
- Google Android操作系统内核编译图文教程
- Android中的消息机制
- Android(安卓)进度暂停和继续
- Chronometer android计时器组件Chronometer的使用,android通话时
- Android(安卓)文件操作