最近半年多的时间都在写iOS,Android不少东西都在忘却中。脑容量不足哇。html
虽然作了2年多的android开发,但基础知识总感受不是很牢固。linux
基于以上两点,打算从新整理一下Android知识。从Android Guide入手。android
对于读者,很是感谢抽出时间来看个人笔记,如有什么错误请指正。有什么意见能够私信我。web
虽然从官方的Android Guide开始。安全
但说实话。我以为官方文档并不适合新人(做为新人,我更喜欢iOS的文档,固然也有可能我有android经验。思路会类比一下感受很简单)。多线程
若须要明白个8 9分的东西须要你具有必定的Android项目开发经验才行。app
当咱们启动应用的最开始,先建立了一个linux进程和一个主线程,根据应用须要在建立了其余进程和线程。而后全部的操做化做指令,逐一交付给线程执行。ide
When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution. By default, all components of the same application run in the same process and thread (called the "main" thread). If an application component starts and there already exists a process for that application (because another component from the application exists), then the component is started within that process and uses the same thread of execution. However, you can arrange for different components in your application to run in separate processes, and you can create additional threads for any process.
当启动app是,若当前没有该app的组建(components)运行,那么会建立一个linux进程。函数
默认全部的组建都运行在同一个进程和线程(主线程)。post
若是这个组建启动时,要启动的进程已经存在,则执行这个组建在这个进程的主线程中。
你能够建立不一样的进程和线程。
组建(components)是指: activity, service, receiver, provider
能够经过设置AndroidManifest.xml中的组建属性"android:process"来肯定运行在其余进程。
<service android:name=".demo.service.remind.TYRemindServiceImpl" android:process="remindservice" /> <!-- remindservice --> <service android:name=".demo.service.remind.TYRemindServiceImpl" android:process=":remindservice" /> <!-- :的做用:使得该线程名为包名:remindservice -->
进程等级
如下是由高等级到低等级的顺序列出全部的进程等级以及他们的断定条件。
Foreground process -- 前台进程
Activity: 已经调用onResume()以后
Service: 已经绑定, 或设置foreground, 或正在执行生命周期的回调函数(onCreate,onStart,onDestory).
这里官方文档没说起onStartCommand,可是在Service中却有体提到.
BroadcastReceiver: 正在执行onReceive
Visible process -- 可见进程
当一个进程没有前台进程,但又正显示在屏幕上:
Activity: 当前Activity是前台进程并执行onPause方法。
Service: 已与前台Activity绑定.
Service process -- 服务进程
正在运行的Service,在经过 startService() 方法启动的Service(由Service可知,并不符合前两个等级)。
Background process -- 后台进程
Activity: 已执行onStop()后.该进程等级的断定下降为后台进程等级。
后台进程对于用户来讲是不可见的,终结进程也不会影响用户体验。
被终结以后,若正确使用状态恢复(详见Activity),用户想要经过"最近访问"重启的时将会和以前的同样。
Empty process -- 空进程
没有任何活动组建时。该进程等级为最低。
存在的意义仅仅是加速再次启动的时间。
这类进程会常常被终结。
如何断定进程的等级
该进程的等级断定受下面两点影响
由所包含的组建的最高等级而定。例如:
一个进程中:Activity为前台进程等级,而且也运行了一个Service,该Service符合服务进程等级。那该进程的等级为前台进程等级。
由依赖进程而定。例如:
ContentProvider正在为另外一进程服务,或Service与另外一进程绑定,那前者的等级老是比后者高。
进程终结时机及策略
当系统内存紧张时,系统选择终结进程的顺序是根据等级由低到高执行。
空进程会常常被回收,Service process以上等级的系统会尽可能保证存活。
因为服务进程等级(Service process)要高于后台进程(Background process)等级。
因此当Activity进入后台时,选择Service处理耗时操做要比使用工做线程要好(如AsyncTask)。
此时至少为Service的进程等级。并且不用考虑Activity是否被销毁。
当BoardCastReceiver执行onReceive的时候,如有耗时操做。则应开启Service而不是选择建立其余线程(如AsyncTask)。
启动应用时,会建立及启动主线程(Main Thread),或称UI线程(UI Thread).
主线程用于分发用户事件(Touch event, drawing event)等。
全部的组建都运行在主线程中。
Andoid UI toolkit(属于android.widget 和 android.view包下的全部类) 均非线程安全。必须在主线程中使用。
主线程中不要作耗时操做,会阻塞用户行为的响应(点击,刷新页面),从而致使ANR的出现
工做线程这个名字一开始让我很困扰。觉得是什么特殊的线程。其实没什么,只是相对于主线程的一种说法。
耗时操做要在这里进行。
若须要刷新UI控件等涉及影响主线程的地方。能够经过一下策略解决
View.post(Runnable) 和 View.postDelayed(Runnable, long) //仅针对View
Activity.runOnUiThread(Runnable) //随时使用
Handler //因为Handler依赖于建立时的线程,因此若主线程刷新。须要在主线程建立Handler,并在工做线程中发消息。
AsyncTask // 这个很少说。详见官方文档。
IntentService // 见其余文档。
下面是例子,均完成相同的操做,工做线程下载图片,通知主线程显示图片。来自官方文档
// 错误例子 new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); // 这是错误的,违反"综述"中的第4条 } }).start(); // 使用Activity Activity activity = this;// 假设获取Activity实例 new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); activity.runOnUiThread(new Runnable() { @Override public void run() { mImageView.setImageBitmap(b); // 这是错误的,违反"综述"中的第4条 } }); } }).start(); // 使用Post public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); } // 使用AsyncTask public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png"); } private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } /** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); } } // 使用Handler // 在主线程建立Handler实例 private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); mImageView.setImageBitmap(msg.obj); } }; new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); Message msg = handler.obtainMessage(0, bitmap); handler.sendMessage(msg); } }).start();
总的来讲,当你使用多线程或多进程时,数据通信是比较繁琐且易出错的工做。
但你可使用Android的一些本地化特性,能够帮你省去不少工做,好比官网举两点的例子。
Service的onBind()方法,此方法执行在主线程,而返回的对象将在线程池中被调用。
ContentProvider和ContentResolver一样隐藏了如何管理进程间通信(IPC),入口看上去仅仅是insert(),delete()等操做。但你能够在任意线程里使用。
官网仅说起了Service 经过绑定进行通信。使用Messenger.这部分之后在作介绍。
了解进程的生命周期很重要,好比重要的耗时工做放在Service中要比AsyncTask要安全。
对于耗时操做,Android提供了多重特性能够应对。并且使用简单。
涉及多线程,多进程的通信,利用特性(Handler,IBinder) 能够简单安全的解决。
数据存储。使用ContentProvider要优于存文件,不用考虑线程安全。