Activity生命周期?保存activity的一些信息在哪个生命周期方法中?
共有七个周期函数:
void onCreate(Bundle savedInstanceState) 第一次创建时调用
void onStart() 被用户可见时调用
void onResume() 当获得焦点即可与用户交互时调用
void onPause() 当失去焦点时调用
void onStop() 当不可见时调用
void onRestart() 当Activity处于stop状态又被重新启动时调用
void onDestroy() 当销毁时调用
onPause() 保存
说说Activity,Intent,Service是什么关系
一个 Activity 通常是一个单独的屏幕,每一个Activity 都被实现为一个单独的类,这些类都是从Activity 基类中继承来的,Activity 类会显示由视图控件组成的用户接口,并对视图控件的事件做出响应。
Intent 的调用是用户进行架构屏幕之间的切换的,Intent 是描述应用想要做什么。Intent 数据结构中两个最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。
Android Service 是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序进程的上下文里。需要通过某一个Activity 或者其他 Context 对象来调用.
Activity 跳转到 Activity ,Activity 启动Service ,Service 打开Activity都需要Intent 表时跳转的意图,以及传递参数,Intent 是这些组件间信号传递的承载者。
BroadcastReceive广播接收器:你的应用可以使用它 对外部事件进行过滤只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。
当系统或用户应用程序发送了某广播之后,符合条件的广播接收者都将收到该条广播。
什么是IntentService,有何优点
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。
android将进程的优先级分为5个层次,按照优先级由高到低排列如下:
- 前台进程(Foreground process)。它表明用户正在与该进程进行交互操作,android系统依据下面的条件来将一个进程标记为前台进程:
- 可见进程(Visible process)。它表明虽然该进程没有持有任何前台组件,但是它还是能够影响到用户看得到的界面。android系统依据下面的条件将一个进程标记为可见进程:
- 服务进程(Service process)。除了符合前台进程和可见进程条件的Service,其它的Service都会被归类为服务进程。
- 后台进程(Background process)。持有不可见Activity(调用了onStop()方法)的进程即为后台进程。通常情况下都会有很多后台进程,当内存不足的时候,在所有的后台进程里面,会按照LRU(最近使用)规则,优先回收最长时间没有使用过的进程。
- 空进程(Empty process)。不持有任何活动组件的进程。保持这种进程只有一个目的,就是为了缓存,以便下一次启动该进程中的组件时能够更快响应。当资源紧张的时候,系统会平衡进程缓存和底层的内核缓存情况进行回收。
Android Jetpack
对于任何一个产品来说,我们开发中都会面对哪些问题?如:产品交互、用户体验、代码结构、数据获取、数据存储、网络优化、任务调度等等,虽然在现在的阶段这些问题已经有了很好的解决和优化,也有很多大神的开源组件方便开发者去使用,Android Jetpack就是Google给出的一个官方的处理方法(当然知识处理其中基本问题),Android Jetpack组件的优势:
轻松管理应用程序的生命周期
构建可观察的数据对象,以便在基础数据库更改时通知视图
存储在应用程序轮换中未销毁的UI相关数据,在界面重建后恢复数据
轻松的实现SQLite数据库
系统自动调度后台任务的执行,优化使用性能
Android Jetpack组件推荐的使用项目架构
上面架构组件的功能如下:
Activity和Fragment负责产品与用户的交互
ViewModel作为数据的存储和驱动
Resposity负责调度数据的获取
Room储存本地序列化的数据
Retrofit获取远程数据的数据
SharedPreferences
/同步保存更改的方法/
boolean commit();
异步保存到磁盘,原子提交,性能更高,不保证结果/
void apply();
- SharedPreferences 是线程安全的. 内部由大量 synchronized 关键字保障
- SharedPreferences 不是进程安全的
Service的详解
Service生命周期可以从两种启动Service的模式开始讲起,分别是context.startService()和context.bindService()。
(1).startService的启动模式下的生命周期:当我们首次使用startService启动一个服务时,系统会实例化一个Service实例,依次调用其onCreate和onStartCommand方法,然后进入运行状态,此后,如果再使用startService启动服务时,不再创建新的服务对象,系统会自动找到刚才创建的Service实例,调用其onStart方法;如果我们想要停掉一个服务,可使用stopService方法,此时onDestroy方法会被调用,需要注意的是,不管前面使用了多个次startService,只需一次stopService,即可停掉服务。
(2).bindService启动模式下的生命周期:在这种模式下,当调用者首次使用bindService绑定一个服务时,系统会实例化一个Service实例,并一次调用其onCreate方法和onBind方法,然后调用者就可以和服务进行交互了,此后,如果再次使用bindService绑定服务,系统不会创建新的Service实例,也不会再调用onBind方法;如果我们需要解除与这个服务的绑定,可使用unbindService方法,此时onUnbind方法和onDestroy方法会被调用。
两种模式有以下几点不同之处:startService模式下调用者与服务无必然联系,即使调用者结束了自己的生命周期,只要没有使用stopService方法停止这个服务,服务仍会运行;通常情况下,bindService模式下服务是与调用者生死与共的,在绑定结束之后,一旦调用者被销毁,服务也就立即终止
Service 进程内与服务通信
进程内与服务通信实际上就是通过bindService的方式与服务绑定,获取到通信中介Binder实例,然后通过调用这个实例的方法,完成对服务的各种操作。
应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder.
绑定是异步的.bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传给bindService().ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder.
IBinder是接口,你看前面有个I,理解为接口,他的实现类必须自己编写代码逻辑来实现功能。
Binder是实现了IBinder的具体实现类,他具有具体的功能,继承了Binder的类就是IBinder对象了。
服务端
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind called.");
return new MyBinder();
}
/**
* 绑定对象
*
* @author user
*/
public class MyBinder extends Binder {
//Activity调用
public void greet(String name) {
Log.i(TAG, "hello, " + name);
}
}
Activity里面 的代码。
bindService(intent, conn, Context.BIND_AUTO_CREATE);
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//connected
binder = (MyService.MyBinder) service; //获取其实例Service里面的MyBinder
binder.greet("scott"); //调用其方法
Log.i("MyService", "onServiceConnected called.");
}
/**
* Called when a connection to the Service has been lost.
* This typically happens when the process hosting the service has crashed or been killed.
* This does not remove the ServiceConnection itself.
* this binding to the service will remain active,
* and you will receive a call to onServiceConnected when the Service is next running.
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
AIDL实现跨进程通讯
服务端
新建AIDL接口 编译器会自动生成一个和AIDL名字相同的JAVA类,这个 .java 文件才是与我们的跨进程通信密切相关的东西。
在服务端实现AIDL中定义的方法接口的具体逻辑,然后在客户端调用这些方法接口,AIDL接口相当于暴露出去可以给其他应用调用
写服务端代码的时候,第一块是初始化。在 onCreate() 方法里面我进行了一些数据的初始化操作。第二块是重写 BookManager.Stub 中的方法。在这里面提供AIDL里面定义的方法接口的具体实现逻辑。第三块是重写 onBind() 方法。在里面返回写好的 BookManager.Stub 。
客户端和服务端AIDL的包名必须完全一致。
客户端:
客户端我们要完成的工作主要是调用服务端的方法,但是在那之前,我们首先要连接上服务端,
首先bindService()建立连接,然后在 ServiceConnection 里面获取 服务端的AIDL接口 对象,(方法返回我们的接口的引用。接着客户端就可以通过它来对服务端发送请求了)
两种AIDL文件:在我的理解里,所有的AIDL文件大致可以
分为两类。一类是用来定义parcelable对象,以供其他AIDL文件使用AIDL中非默认支持的数据类型的。一类是用来定义方法接口,以供系统使用来完成跨进程通信的
AIDL可用数据类型
Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。
String 类型。
CharSequence类型。
List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。List可以使用泛型
Map类型 Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的
哪些地方是执行在主线程的
- [Activity的所有生命周期(https://www.jianshu.com/p/ec6984aa1bb4)都是执行在主线程的.
- Service默认是执行在主线程的
- BroadcastReceiver的onReceive回调是执行在主线程的.
- 没有使用子线程的looper的Handler的handleMessage, post(Runnable)是执行在主线程的.
- AsyncTask的回调中除了doInBackground, 其他都是执行在主线程的.
- View的post(Runnable)是执行在主线程的.
android如何动态刷新UI
1.利用Looper更新UI界面
2.AsyncTask利用线程任务异步更新UI界面 如果是后台任务,像是下载任务等,就需要使用AsyncTask。
3.利用Runnable更新UI界面
请描述一下Intent 和 Intent Filter。
Intent在Android中被翻译为"意图",熟语来讲就是目的,他们是三种应用程序基本组件—activity,service和broadcast receiver之间互相激活的手段。在调用Intent名称时使用ComponentName也就是类的全名时为显示调用。这种方式一般用于应用程序的内部调用,因为你不一定会知道别人写的类的全名。我们来看看隐式Intent怎么用?首先我们先配置我们的Activity的Intent Filter
这样在调用的时候指定Intent的action,系统就是自动的去对比是哪个intent-filter符合我们的Activity,找到后就会启动Activity。
一个intent filter是IntentFilter类的实例, 但是它一般不出现在代码中,而是出现在android Manifest文件中, 以
一个filter有action, data, category等字段. 一个隐式intent为了能被某个intent filter接受, 必须通过3个测试. 一个intent为了被某个组件接受, 则必须通过它所有的intent filter中的一个.
广播如何调用,有什么方式,各自的区别?
程序中发送广播通过sendBroadcastReceiver()实现
接收广播通过定义一个类继承BroadcastReceiver并重写onReceive()方法实现
注册广播有两种方式:
第一种静态方式:在清单文件中通过
第二种代码动态方式:
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomgSMSReceiver();
registerReceiver(receiver.filter);
1)第二种不是常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。
2)第一种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
Android中asset文件夹和raw文件夹区别?
res/raw和assets的相同点:
两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。
res/raw和assets的不同点:
1)res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即 R.raw.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。
2)res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹
3)读取文件资源举例:
读取res/raw下的文件资源,通过以下方式获取输入流来进行写操作
InputStream is = getResources().openRawResource(R.raw.filename);
读取assets下的文件资源,通过以下方式获取输入流来进行写操作
AssetManager am = null;
am = getAssets();
InputStream is = am.open("filename");
android系统架构
1)应用程序层 java语言 应用程序开发
2)应用程序框架层 java语言 OS定制 framework层开发
3)系统运行库层 C C++ 实现 so库
4)Linux内核层
请介绍下Android的数据存储方式。
使用SharedPreferences存储数据;
文件存储数据;
SQLite数据库存储数据;
使用ContentProvider存储数据;
网络存储数据
请介绍下ContentProvider是如何实现数据共享的。
答:当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。
虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;
采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。
而使用ContentProvider共享数据的好处是统一了数据访问方式。
当应用需要通过ContentProvider对外共享数据时,
第一步需要继承ContentProvider并重写下面方法:
第二步需要在AndroidManifest.xml使用
你后台的Activity被系统回收怎么办? 如何在回收之前保存当前状态
当一个Activity被pause或者stop的时候,这个Activity的对象实际上还是保存在内存中,因此这个Activity中的信息(成员和状态信息)还可以重新获取到.
如果系统为了整理内存而销毁了整合各Activity对象时,系统没法简单的原封不动地恢复先前的Activity对象及其状态信息. Activity中提供了一个方法:onSavedInstanceState(Bundle obj).当系统销毁一个Activity时,会将Activity的状态信息已键值对形式存放在bundle对象中.
第一次启动Activity时,这个bundle对象是空的,null.如果Activity被系统销毁了,然后用户要回退回去看的话,系统会调用这个Activity的onCreate方法,并把bundle对象传递过去.
这个函数有默认的行为,因此就算你不覆盖它,它在Activity中也有实现.
另外,刚才查看了一下Activity的源码,发现Activity还有个onRestoreInstanceState(Bundle outState)方法.这个方法的描述中也写到在Activity恢复先前保存的状态时会被调用.
第二种情况 在OnStop中保存状态在本地,然后在OnResume中本地恢复状态。
如何将一个Activity设置成窗口的样式。 ]
1.在你的styles.xml文件-中可以新建一如下的style: