android-基础知识解析
1、四大组件
android:launchMode="singleInstance"/"singleTop"/"singleTask"/"standard"
standard 普通的开启模式:按开启的顺序入栈,出栈
singleTask 整个栈里只能有一个实例 特点: 当再次调用他他会把他上面的activity全部销毁,他到达栈顶。
singleTop 栈里可以有多个实例,但栈顶只能有一个实例
singleInstance 自己开辟一个单独的栈 并且栈里面只有一个实例 整个栈里只有一个activity
如果已经存在了一个栈,并存在相同的实例,那么就不会再继续创建栈了,而是复用这个已经存在的栈和实例。经验证确实是栈里面只有一个activity。
【2】四大组件都不能进行耗时操作,执行耗时操作必须开子线程。
【3】可以为四大组件单独开一个进程
【4】进程的lifecycle
foregound Process 一个activity执行了并处于 onResume状态 broadcastReceiver正在执行
onReceive方法 service正在执行生命周期方法,调用startforeground,绑定的activity正在和用户交互。
visible process
activity执行onpause 处于可见不可操作的状态 如果service单独开启一个process 他绑定的
activity处于onpause状态 该process处于visiable process
service process
应用ui不可见,后台只跑着一个service 后台播放音乐 执行联网下载
background process 后台有activity执行onstop 处于不可见不可操作转态 处于后台进程的应用很多,采用LRU算法决定处于后台进程的那个应用被干掉,最近最少使用最先被杀死
empty process 没有任何组件在运行 下次启动的时候提高启动的时间
【5】activity lifecycle
If an activity is paused or stopped, the system can drop it from memory either by asking it tofinish (calling its finish()
method), or simply killing its
process.
如果一个activity处于onPause或onStop状态 系统回收他两种方式 调用他的finish() 或直接杀掉进程
The visible lifetime of an activity happens between the call toonStart()
and the call toonStop()
.
The foreground lifetime of an activity happens between the call toonResume()
and the call toonPause()
.
onDestoty()
it could be called either because the activity is finishing (someone called finish()
on it), or because the system is temporarily destroying thisinstance of the activity to save space. finish()走的是onDestory().
【6】thread-safe
如果同一时间有多个线程调用同一个对象的方法,就会出现thread-unsafe
【7】UI thread and work thread
应用的进程里 除了 ui thread 其他用于执行耗时操作的线程都是 work thread
【8】activity屏幕方向切换走的生命周期方法
切屏 onDestory() 然后立刻走onCreate()
如何处理重启的问题呢?
方式一:针对数据较少的情况
@override onSavaInstanceSatate() 在他里面做保存工作
切屏走onDetory()之前 系统自动调用 onSavaInstanceState()
重新走onCreate() 在onCreate()或onRestoreInstanceState()里再取出保存的状态
方式二:针对大数据的情况
To retain an object during a runtime configuration change:
- Override the
onRetainNonConfigurationInstance()
method to return the object you would like to retain.重写 - When your activity is created again, call
getLastNonConfigurationInstance()
to recover your object.自己手动调用
@override onRetainNonConfigrationInstance() 返回一个object 用于保存状态 不能返回和上下文相关的对象 否则会造成内存泄露
在onStop()和onDestory()之间调用
在onCreate()方法里调用、getLastNonConfigurationInstance() 返回之前保存的对象
handling the configration change by yourself
自己处理屏幕的切换事件,系统就不重启activity了,但系统会发广播,通知你屏幕有变化
重写onConfigrationChanged()处理屏幕的切换事件。
To declare that your activity handles a configuration change, edit the
appropriate <activity>
element in your manifest file to include the
android:configChanges
attribute with a value that represents the configuration you want to handle.
注意:
Note: If your application targets API level 13 or higher (as declared by the
minSdkVersion
andtargetSdkVersion
attributes), then you should also declare the"screenSize"
configuration, because it also changes when a device switches between portrait and landscape orientations.
例如:屏幕虽然切换,但是他走onDestory()和onCreate(),而是维护原来的转态继续运行,
只是当切换屏幕的时候,onConfigrationChanged()会被调用
api level >= 13
orientation|screenSize 必须成对出现
<activity
android:name=".MainActivity" android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
For example, the following manifest code declares an activity that handles both the screen orientation change and keyboard availability change:
api level < 13
<activity android:name=".MyActivity"android:configChanges="orientation|keyboardHidden"android:label="@string/app_name">
不管API level 为啥,都要走onConfigrationChanged().
Now, when one of these configurations change, MyActivity
does not restart.
Instead, theMyActivity
receives a call toonConfigurationChanged()
.
@Override public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);// Checks the orientation of the screenif (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();} }
1.2 startService()和bindService()深入理解
混合开启开启的是同一个service对象,
unbindService(sc);//只是取消service和当前activity的绑定,并没有关闭service stopService(intent);//彻底关闭service
下面流程写的非常详细:
- 一个Intent对象最多只能包含一个Action属性,程序可调用Intent的setAction(String str)方法来设置Action属性值
- 一个Intent对象可以包含多个Category属性,程序可调用Intent的addCategory(String str)方法来为Category属性
- 当程序创建Intent时,该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量(常量值为android.intent.category.DEFAULT)的组件
- 对于Service 通过隐式意图开启服务,并不需要category。
不要在广播里添加过多逻辑或者进行任何耗时操作,因为在广播中是不允许开辟线程的,
当onReceiver( )方法运行较长时间(超过10秒)还没有结束的话,那么程序会报错(ANR),
广播更多的时候扮演的是一个打开其他组件的角色,比如启动Service,Notification提示, Activity等!
Android offers a mechanism for interprocess communication (IPC) using remote procedure calls (RPCs), in
android通过rpc来实现ipc
which a method is called by an activity or other application component, but executed remotely (in another
远程的方法被本地activity调用或其他应用的组件调用
process), with any result returned back to the caller. This entails decomposing a method call and its data to a
方法在远程执行 并把执行的结果返回给调用者 这其中涉及到方法是如何调用的,数据是如何传递的
level the operating system can understand,
只有操作系统能够明白
Android provides all the code to perform these IPC transactions, so you can focus on defining and
这其中的代码都有android系统来完成 你的关注点在如何定义接口
implementing the RPC programming interface.
和如何远程调用
To perform IPC, your application must bind to a service, using bindService()
.
为了执行ipc,你的应用必须绑定bindService()
一、谨慎选择包名
案例一
案例二
二、一款应用只应该有一个签名
案例一
案例二
三、使用 xml 配置文件来区分渠道
一般来说,我们在 Android manifest 文件中使用 meta-data 来区分渠道。例如:
1
|
<meta-data android:name= "CHANNEL" android:value= "wandoujia" />
|
每次正式打包完成后,修改 android:value,再重新打包即可生成一个新的渠道包,所以:
不要再用签名来区分渠道了!
四、正确填写版本号在 Android 应用中,有两个参数与版本号相关。其中,version Name 表示版本名称,是字符串,version Code 表示版本号,是整型数字。一般来说,用户直观看到的是 version Name,所以这里应该填写形似“4.15.1”这样的版本号。而真正用来判断新版本旧版本的参数是 version Code。在应用发布第一个版本的时候,version Code 应该填 1,然后每次发布的时候都递增,这样才是以规范的格式告诉各大市场你的应用的更新程度。有的开发者在 version Code 上非常随意,这个版本发布的时候碰上结婚纪念日,于是用老婆的生日当 version Code;下个版本发布的时候运气不太好,于是用自己的幸运数字当作 version Code……这样在用户看来的结果就是,明明从官网安装了最新的 2.2.0 版本,可是各大市场却提醒“升级到 2.1.3 版本”,越升级版本号越小了。以上四件小事,虽然都比较琐碎,而且没什么技术含量,但却是很多入门的 Android 开发者容易忽略的问题。希望本文能帮助广大开发者,在写出好应用的同时,避免这些“坑”给应用带来不必要的损失。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.bilibili.secondActivity"/>
<!--必须指定category-->
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Thread.currentThread().getName();可以获取任意线程的名称
线程调度 抢占式 getPriority() setPriority(int priority)
线程退出 run()代码执行完毕 手动调用stop()
线程池 jdk5.0 以来使用 Executors 工厂类来产生线程池
ExecutorService 对象表示线程池
线程池 框架
Executors
ExecutorService 线程池
ThreadPoolExecutor
SchedualThreadPoolExecutor
构建线程对象
Runable
Callable
线程池实例(单例)把线程对象提交给线程池submit(thread)/execute(thread) 系统自动执行线程实例
创建线程池对象
创建runnable对象
线程池对象调用submit()或execute()把任务提交到线程池,开始执行线程。
ExecutorService executorService = Executors.newFixedThreadPool(6);
Runnable runnable = new Runnable() {
@Override
public void run() {
}
};
executorService.submit(runnable);/executorService.execute(runnable);
LogUtil.logi(this.getClass(),File.separator);// "/" LogUtil.logi(this.getClass(),File.pathSeparator);// ":"
如果你的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP,此外OkHttp还处理了代理服务器问题和SSL握手失败问题。
首先介绍下OkHttp的简单使用,主要包含:
- 同步/异步get请求
- 同步/异步post请求
- 基于Http的文件上传
- 文件下载
- 加载图片
- 支持请求回调,直接返回对象、对象集合
- 支持session的保持
http请求方式 : get、post 最常用
其他请求方式 patch、put
其中okHttp除了支持 get/post请求之外还支持其他请求方式
okHttp自带缓存机制,可以对请求的数据进行磁盘缓存 Okhttp已经内置了缓存,默认是不使用的,如果想使用缓存我们需要手动设置
在okHttpClient构造时设置缓存路径
构造Request实例时配置缓存策略
http://blog.csdn.net/u012702547/article/details/53143322?locationNum=8&fps=1
创建带缓存的okHttp实例 ,构造缓存路径
一般磁盘缓存都是放在和diskLruCache缓存一样的sd卡
创建请求Request实例 配合缓存策略
get请求
同步请求,需要自己开线程
//[1]以同步方式请求网络,需要我们自己开子线
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
try {
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()) {
callback.onSuccess(response.body().bytes());
} else {
callback.onFail(response.message());
Toast.makeText(context, "请求失败", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context, "请求失败", Toast.LENGTH_SHORT).show();
}
}
});
//在request里构建cacheControl
CacheControl cc = new CacheControl.Builder()
// .noCache()//不使用缓存,只走网络
// .noStore()//不使用缓存,但也不保存缓存数据
// .maxAge(5,TimeUnit.SECONDS)//设置最大失效时间,超过这个时间失效,
失效则不用
.maxStale(5,TimeUnit.SECONDS)//设置最大失效时间,超过这个时间失效,失效则不用
// .onlyIfCached()//只使用缓存
// .minFresh(5,TimeUnit.SECONDS)//设置最小有效时间,小于5s失效,大于5s有效,失效则不用
.build();
//[01]get请求,请求参数要放在url里
Request request = new Request.Builder()
.addHeader("header1", "value1")
.addHeader("header2", "value2")
.url(url)
.cacheControl(cc)//缓存策略
.tag(NetUtil.class)
.build();
Request request1 = new Request.Builder()
// .cacheControl(CacheControl.FORCE_CACHE)//强制使用网络
.cacheControl(CacheControl.FORCE_NETWORK)//强制使用缓存
.build();
RequestBody okRequestBody = new FormBody.Builder()
.add("body", getRequestJson(requestParams))
.build();
request = new Request.Builder()
.addHeader("user-agent", "xxxxx")
.addHeader("accept", "yyyy")
.url(url)
.post(okRequestBody)
.build();
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(2000, TimeUnit.MILLISECONDS)
.cache(new Cache(new File(CachePathUtil.externalCacheFile(context)+
File.separator+"net"),
10*1024*1024))//第二个参数表示缓存区的大小为10M,
// 当缓存区的数据大小超过10M的时候会自动删除已缓存的数据
.build();
//[2]异步线程请求,okHttp内部开子线程
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Toast.makeText(context, "请求失败", Toast.LENGTH_SHORT).show();
callback.onFail(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
callback.onSuccess(response.body().bytes());
}
});
在构造Request的时候,我们可以配置CacheControl,配置有两种方式,一种是构造CacheControl,还有一种是直接使用CacheControl中的常量,
如果服务器的响应头里没有cache-age字段,我们通过Interceptor拦截响应,并在客户端强行添加一个cache-age字段,并指定值。这时就能达到缓存的目的。
//Retrofit、Picasso等配合OkHttp使用的框架
public static <T> void getDataFromNet(final Context context,
String url,
Map<String, Object> requestParams,
final ReqCallback callback) {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(2000, TimeUnit.MILLISECONDS)
.writeTimeout(2,TimeUnit.MINUTES)
.readTimeout(2,TimeUnit.MINUTES)
// .addInterceptor(new MyIntercaptor())//强行修改request和response头
.cache(new Cache(new File(CachePathUtil.externalCacheFile(context) +
File.separator + "net"),
10 * 1024 * 1024))//第二个参数表示缓存区的大小为10M,
// 当缓存区的数据大小超过10M的时候会自动删除已缓存的数据
.build();
}
String requestJson = getRequestJson(requestParams);
// RequestBody requestBody = RequestBody.create(MediaType.parse("json"), requestJson);
//abstract class RequestBody
// FormBody(表单) extends RequestBody
//MultipartBody extends RequestBody
FormBody requestBody = new FormBody.Builder()
.add("data",requestJson)
.build();
// MultipartBody multipartBody = new MultipartBody.Builder()
// .build();
//告诉okHttp缓存的有效期,和响应头的cache-control或者是interceptor的作用是一样的。所以4选一
CacheControl cc = new CacheControl.Builder()
.maxAge(5, TimeUnit.MINUTES)//5分钟之内的有效
.build();
Request request = new Request.Builder()
.url(url)
.tag("tag1")
// .cacheControl(CacheControl.FORCE_NETWORK)
.cacheControl(cc)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
//响应头里没有cache-control,我们就强行加上;否则,就不需要用Interceptor实例了
private static class MyIntercaptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
return response.newBuilder()
.removeHeader("Pragma")
.removeHeader("Cache-control")
.header("Cache-control","max-age="+3600*24*30)
.build();
}
}
它是用来证明某某东西确实是某某东西的东西(是不是像绕口令?)。通俗地说,证书就好比例子里面的公章。通过公章,可以证明该介绍信确实是对应的公司发出的。
理论上,人人都可以找个证书工具,自己做一个证书。那如何防止坏人自己制作证书出来骗人捏?请看后续 CA 的介绍。
到了1999年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是“Transport Layer Security”的缩写),中文叫做“传输层安全协议”。
很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。
android-基础知识解析相关推荐
- 100天精通Andriod逆向——第2天:Android基础知识和jadx的使用
目录 一.Android基础知识介绍 1.1 Android 历史版本 1.2 apk 包文件结构 1.3 Android系统目录介绍 二.jadx的使用 2.1 jadx 的简介 2.2 jadx ...
- Android基础知识——完善
首页 下载App × Android基础知识--完善 布鲁马 2016.05.17 10:29* 字数 5478 阅读 2672评论 1喜欢 38 疯狂Android摘要,Android基础知识好乱好 ...
- android基础知识
技术型男 随笔 - 20, 文章 - 0, 评论 - 4, 引用 - 0 android基础知识 1. 前言 1.1. 什么是3G.4G Ÿ 第三代移动通信技术(3rd - Generation),速 ...
- Android基础知识(二十一):Android五大存储之文件存储、Content Provider存储和网络存储
Android基础知识(二十一):Android五大存储之文件存储.Content Provider存储和网络存储 一.Android存储--持久化技术 数据持久化是指将那些内存中的瞬时数据保存到存储 ...
- Android基础知识巩固系列 Android之四大组件——ContentProvider(内容提供者)
因为最近要面试,于是打算整理整理一下Android的基础知识,由于之前本人已经学习过大概的Android基础知识,这里主要讲这四大组件.五大存储.六大布局.网络请求等这些内容,其他一些等有时间再整理, ...
- Android基础知识:在UI线程中运行代码
本文翻译自:Android basics: running code in the UI thread In the viewpoint of running code in the UI threa ...
- Android基础知识(二十):Notification、提醒式通知(横幅)踩坑与通知界面设置跳转
Android基础知识(二十):Notification.提醒式通知(横幅)踩坑与通知界面设置跳转 一.Notification通知与基本用法 通知Notification是Android系统中比较有 ...
- Android基础知识【项目实训-实现二级导航“今日活动”及读取数据库】【5】
[该项目实训是Android基础知识的一个综合练习,特别提示:项目中会用到一些图片素材,都是随意整理的,稍后会上传一个资源,包含该事项项目的基本功能,也含有图片素材] [项目题目]:校园订餐App设计 ...
- Android 基础知识+app测试权限问题
Android 基础知识(权限篇)** 前言 Android是一个开源的,基于Linux的移动设备操作系统,主要用于移动设备,如智能手机和平板电脑.Android是由谷歌及其他公司带领的开放手机联 ...
- 捷联惯导基础知识解析之五(低成本姿态航向参考系统)
陀螺仪精度0.1°/s:加速度计精度5mg:主要指零偏重复性! 一.简化的惯导算法 1.姿态更新 陀螺仪输出直接进行积分,得到角增量: 2.速度更新: 在导航系下,完整的速度微分方程,如下: 其中,在 ...
最新文章
- 了解下C# 类型转换
- iOS程序启动画面的制作
- 喜提 Go Contributor
- Bootstrap3 栅格系统-栅格参数
- How to get list of all public urls which are using BSP UI technology
- Java面向对象(20)--接口
- C#中IEnumerableT.Distinct()将指定实体类对象用Lambda表达式实现多条件去重
- PCL学习笔记02:在ROS下建立编译链接PCL模块
- POJ3264——Balanced Lineup(线段树)
- 理财非保本浮动收益型什么意思?
- java 23种设计模式学习。
- trueOS能装linux软件,GhostBSD 19.09 发布,使用来自TrueOS软件包
- TI公司CC系列的各种芯片的区别 CC2430 CC1100
- tauri打包慢:解决tauri的打包慢以及超时的方法
- 方法重写的一大两小两同
- iOS系统 查看设备序列号 获取UDID
- Python 数据分析 —— Numpy
- Linux查看系统信息命令总结
- 苹果AR/VR设备或定价2000美元 或命名Apple Vision
- wap手机广告形式有哪些形式——手机站点广告代码
热门文章
- linux 下切换集成显卡和独立显卡,禁用独显,解决发热问题
- 聊聊 Kafka: Kafka 为啥这么快?
- Python解题 - CSDN周赛第32期 - 运输石油(三维背包)
- java socket telnet_使用java简单模拟ping和telnet的实现
- 计算机教育专业委员会开会,2017全国高校计算机教育大会在并召开
- 鸿蒙科学实验课,科学小实验 点亮大梦想-长春市第五十二中学开封校区开展科学实验课活动...
- 字符串的相关操作,例子以及应用
- 连云港千卓贸易有限公司
- 用命令行无法运行PostgreSQL命令的问题
- Event-----事件类型:基本类型