五、Android开发基础知识

2023-11-05

android系统一共分为四层:application(java应用程序)、Framework(java框架或系统服务)、Library(本地框架或本地服务又称为Native)+Android Runtime(java运行环境)、Linux Kernel(Linux内核空间)
Framework中与应用直接关联,主要是一些系统服务:activity manager、Window Manager、Package Manager、(UI系统)View System与应用紧密相连;

(一)、Android四种LanchMode(启动模式)

Activity有四种启动模式:standard(默认,标准模式)、singleTop(栈顶复用模式)、singleTask(栈内复用模式)、singleInstance(单例模式)

启动模式的设置方式有两种:直接在AndroidMainifest中使用lanceMode;在代码中通过Intent设置标志位。其中Intent优先级别 > AndroidMainifest优先级别

一)、standard(标准模式,未写时默认为此模式)

每点击显示一次此Activity,就会创建一个新的activity实例,因此会在栈中存在多个此实例

二)、singleTop(栈顶复用模式)

启动此activity时,如果此activity已经处于栈顶,则直接使用此activity,不会创建新的activity实例;相反如果此activity不再栈顶时会重新创建一个新的activity实例

三)、singleTask(栈内复用模式)

启动此activity时,如果此activity已经处于栈内,则直接回退,使用此activity实例,此activity实例之上的活动移除出栈;如果此活动没有处于栈内,则会直接创建一个新的activity实例;
使用此模式的activity会有属于自己单独的Task(命名aTask)。在一个调用此activity的app(其task命名bTask)中,aTask会连同activity一起覆盖到bTask上。之后另一个app(其task命名cTask)调用此activity,aTask将保持activity的原状态移动到cTask内,而bTask中此时是没有activity的。

四)、singleInstance(单例模式)

启动此activity时,会创建一个新的返回栈,其他活动调用它时
在这里插入图片描述

(二)、常用UI控件与事件处理机制

5

一)、View与ViewGroup概念

5

二)、布局

55

1. LinearLayout(线性布局)

5

2. RelativeLayout(相对布局)

5

3. TableLayout(表格布局)

5

4. FrameLayout(帧布局)

5

5. GridLayout(⽹格布局)

5

6. AbsoluteLayout(绝对布局)

5

7. Constraintlayout约束布局

宽高比:高宽为0dp,使用app:layout_constraintDimensionRatio=“h,16:7” 属性
/宽高至少一个设置为0dp,h(w)指明约束的是高(宽)
宽高比:高宽为0

三)、常用基本控件

  1. toolbar收缩与扩展
需要CoordinatorLayoutAPPBarLayout的配合,以及实现NestedScrollView的布局或者控件
AppBarLayout:支持响应滚动手势的appbar布局
adjustViewBounds:可选值
CollapsingToolbarLayout:实现子布局内不同元素响应滚动细节的布局
  1. TextView文本框
    部分属性:
Textstyle:字体风格,可选值有三个值normal(无效果),bold(加粗),italic斜体
shadowColor:设置阴影颜色,
shadowRadius:设置阴影的模糊程度
shadowDx:设置阴影水平方向的偏移
shadowDy:设置阴影竖直方向的偏移
autoLink:识别链接类型,可选值:phone、email、web、all(包含所有类型)等,在代码中可以调用setAutoLInkMAsk(Linkify.ALL),同时还要设置setMovementMethod(LinkMovementMethod.getInstance());(不加,点击无效果)
ellipsize:省略功能,可选择的值有:end,start,middle,marquee
其中marquee表示跑马灯效果,其他为省略号位置(需要与maxLines属性配合使用)

部分属性:
使用拼接字符串时:

String.format(“字符串%s字符串”+”拼接内容”)

SpannableStringSpannableStringBuilder定制文本:
可以对字符串中特定位置的字符制定特效:
SpannableStringBuilder str=new SpannableStringBuilder(“字符串”);
Str.setSPan(new 特效方法(),int(起始位置),int (结束位置),int (flag特定的数值))

特效方法有:

BackgroundColorSpan 背景色
ClickableSpan 文本可点击,有点击事件
ForegroundColorSpan 文本颜色(前景色)
MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
MetricAffectingSpan 父类,一般不用
RasterizerSpan 光栅效果
StrikethroughSpan 删除线(中划线)
SuggestionSpan 相当于占位符
UnderlineSpan 下划线
AbsoluteSizeSpan 绝对大小(文本字体)
DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
ImageSpan 图片
RelativeSizeSpan 相对大小(文本字体)
ReplacementSpan 父类,一般不用
ScaleXSpan 基于x轴缩放
StyleSpan 字体样式:粗体、斜体等
SubscriptSpan 下标(数学公式会用到)
SuperscriptSpan 上标(数学公式会用到)
TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
TypefaceSpan 文本字体
URLSpan 文本超链接
  1. ImageView图片
    scaleType:图片缩放,主要有三种类型:fit类(4个),center类(3个),matrix类(1个),可选值:fitXY(xy方向缩放适配控件)、fitStart(图片大小不变,起始位置靠左)、fitCenter(默认值,图片大小不变,位置中间)、fitEnd(图片大小,位置靠右)、center()、centerCrop()、centerInside()、matrix()
    4.SwipeRefreshLayout下拉刷新(PullToRefreshListView)
    实现下拉刷新,配合滑动监听判断可以实现上拉监听,有五个方法:setOnRefreshListener()、setProgressBackgroundColor()、setColorSchemeResources()、setRefreshing()、setSize()
    注:不需要使用刷新功能时使用setEnable()禁止;是否正在主动显示刷新进度isRefershing();
setOnRefreshListener:设置手势滑动监听器
adjustViewBounds:可选值

setProgressBackgroundColor:设置进度圈的被景色
adjustViewBounds:可选值

setColorSchemeResources:设置进度动画的颜色
adjustViewBounds:可选值

setRefreshing():设置组件的刷洗状态
adjustViewBounds:可选值
setSize():设置进度圈的大小
可选值:SwipeRefreshLayout.LARGE和SwipeRefreshLayout.DEFAULT(系统默认效果)
  1. RecyclerView列表
    部分属性:
//实现瀑布流
StaggeredGridLayoutManager,layoutManager=new,StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);//解决item跳动(不为隐藏布局边缘差距做任何处理)
Recycler.setItemAnimator(null);
Recycler.setHasFixedSize(true);
Recycler.setLayoutManager(layoutManager);
  1. EditView输入框
    adjustViewBounds:可选值未布尔型;功能通过调整ImageView的界限来体调整图片的宽高比例。

四)、日期类控件

五)、Adapter控件

六)、提示类控件

七)、菜单类控件

八)、其他控件

九)、事件处理机制

(三)、Android四大组件和Intent组件

一)、Activity

二)、Service

三)、VroadCastReceiver

四)、ContentProvider

五)、Intent —组件之间的枢纽

Fragment:(代言中指纹识别)
在frament中使用intent中的startActivityForResult方法时,可以直接在fragment中编写,但是回调onActivityResult的方法也是需要写在fragment中,但是不需要再写super(requestCode,resultCode,data);
Dialog:(自定义dialog,Image View从相机/拍照中获取图片显示)
在dialog中使用startActivityForResult(@NonNull Activity activity,@NonNull Intent intent,int requestCode,@Nullable Bundle options),此时回调onActivityResult方法是写在dialog依附的Activity类中的。
getGalleryIntent(intent);

(四)、Fragment

(五)、数据存储

Android数据存储与访问方式有四种方式:文件的存储与读写、SharedPreferences保存用户偏好参数、和SQLite数据库;
Android是基于Linux,在读写文件时,需要加上文件的操作模式,Android中操作模式如下:

注:目前MODE_WORLD_READABLE与MODE_WORD_WRITEABLE已经过时。不推荐使用

(六)、网络编程

一)、网络加载框架Okhttp

5Retrofit是Square公司推出的一个基于RESTful风格的HTTP网络加载架构,它基于OkHttp之上,它的底层是使用OkHttp封装,也就是

  1. 基本网络请求HttpUrlConnection
    Android SDK对HTTP也提供了很好的支持,包括两个接口:
    标准java 接口(Java.NET)–HttpURLConnection,可以实现简单的基于URL请求、响应功能;
    Apache接口(org.appache.http)–HttpClient,使用起来更方面更强大。(API23之后,被移除)

二)、网络加载框架 —Retrofit

Retrofit是Square公司推出的一个基于RESTful风格的HTTP网络加载架构,它基于OkHttp之上,它的底层是使用OkHttp封装,也就是对OkHttp网络请求框架的二次封装,它的网络请求本质是OkHttp完成,Retrofit仅仅负责网络请求接口的封装。这两者都是属于square公司。

注:java.net.UnknownServiceException: CLEARTEXT communication to 192.168.0.108 not permitted by network security policy:google要求应用进程默认使用加密连接,Android p禁止app使用未加密的连接。
解决方法:1、App改使用https请求;2、targetSdkVersion降到27以下;3、更改网络安全配置

1. 与OkHttp的关系

• App应用程序通过Retrofit请求网络,实际上是使用Retrofit接口层封装请求参数、Header、Url等信息,之后由OkHttp完成后续的请求操作。
• 在服务端返回数据之后,OkHttp将原始的结果交给Retrofit,Retrofit会根据用户的需求对结果进行解析。
• 通过使用大量的设计模式进行功能模块的解耦,使得上面的过程进行得更加简单和流畅。

Retrofit的好处:
• 遵循Restful API设计风格,简洁易用
• 支持同步&异步网络请求
• 支持多种数据的解析&序列化格式(Gson、 Json、XML、 Protobuf)
• 支持对RxJava支持
• 注解化配置高度解耦、采用大量设计模式简化使用

2. Retrofit中注解

Retrfit中有24个注解,其中有12个方法注解,12个参数注解;
12个方法注解:

8个HTTP请求注解;

注解名 解释 作用域
@GET 所有方法分别对应htpp中的网络请求方法:都接收一个网络地址url(也可以不指定,通过@http设置) 网络请求接口的方法
@POST 同上 同上
@PUT 同上 同上
@DELETE 同上 同上
@PATH 同上 同上
@HEAD 同上 同上
@OPTIONS 同上 同上
@HTTP 用于替换以上7个注解的作用及更多功能拓展 同上

3个标记注解

注解名 解释 作用域
@FormUrlEncoded 表示请求体是一个form表单;用于修饰Field注解和FieldMap注解,可以自动将请求参数类型调整为application/x-www-form-urlencoded 网络请求接口的方法
@Multipart 表示请求体是一个支持文件上传的form表单 同上
@Streaming 表示返回的数据以流的形式返回;使用与返回数据较大的场景;(如果没有使用该注解,默认把数据全部载入内存,之后获取数据也是从内存中读取) 同上

1个请求头注解

注解名 解释 作用域
@Headers 添加请求头 网络请求接口的方法

12个参数注解:

注解名 解释 作用域
@Header 添加不固定值的header 网络请求接口的方法的参数(如Call<> getCall()中的
@Body 用于非表单请求体;相当于多个Field,以对象的形式提交 同上
@Field 向Post表单传入键值对;用于POST请求,提交单个数据;使用时需要添加FormUrlEncoded 同上
@FieldMap 同上 同上
@Part 用于表单字段;适用于有文件上传的情况
@PartMap 同上 同上
@Query 用于表单字段;URL问号后面的参数;功能同@Field与@FieldMap;(区别在于@Query和@QueryMap的数据体现在URL上,@Field与@FieldMap的数据体现在请求体上,但生成的数据是一致的。) 同上
@QueryMap 同上;相当于多个Query 同上
@Path URL缺省值;所有网址中参数(URL的问号前面) 同上
@URL URL设置值 同上

3. 使用步骤

  1. 在app文件包下build.gradle添加Retrofit库、OkHttp库、数据解析器继承库的依赖
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
  1. 在清单文件AndroidManifest.xml中注册权限;
<uses-permission android:name="android.permission.INTERNET"/>
  1. 创建接收服务器返回数据的类
    请求后服务器会返回数据,需要根据返回数据的格式和解析方式来定义实体类Model
public class ResultBean {

    public String code;
    public String Msg;
    
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getMsg() {
        return Msg;
    }

    public void setMsg(String msg) {
        Msg = msg;
    }
}
  1. 创建用于描述网络请求的接口
    定义一个网络请求的接口,接口函数里要定义URL路径、请求参数、返回类型。需要使用注解来描述请求类型和请求参数
//校验手机号
public interface CheckPhone {
    @POST("registerPhone")
    Call<ResultBean> sendCheckPhone(@Body RequestBody requestBody);
}

// 用@POST("URL")声明了URL路径
// 用getCall()接收网络请求数据,并用注解@Query("xxx") 声明了请求参数
// 该方法会返回一个Retrofit的Call对象,这里声明了这个对象处理的数据类型为自定义Model

//       EditmyinfoBean是接收的数据的类型,Call<EditmyinfoBean>返回类型,
//        若想直接获取返回的内容,写为Call<Responsebody>
//        @Query GET请求方式,如果携带的参数不是以?num=10&page=1
//        拼接到接口中(就是不带?分隔符及后面的字符),那就不用Query注解了,而是使用//Path注解

注:@GET和@Query搭配使用,@POST和@Field搭配使用
5. 创建Retrofit对象并设置数据解析

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("URL") 
//设置网络请求的Url地址,注意以要以斜线(代表根目录)结尾
                .addConverterFactory(GsonConverterFactory.create()) 
//设置数据解析器,这里表示用的是JSON解析返回值
                .build();
  1. 生成接口对象
    由于是interface不是class,无法直接调用内部方法,需要利用已创建的Retrofit对象去生成代理的接口对象。
CheckPhone是第四步创建的接口名
CheckPhone checkService=retrofit.create(CheckPhone.class);
  1. 调用接口方法返回Call对象
sendCheckPhone是第四步创建的接口中的方法,phone是RequestBody类型的变量
Call<ResultBean> call=checkService.sendCheckPhone(phone);
  1. 发送网络请求(异步/同步)
a.同步:调用Call对象execute(),返回结果是响应体。

//开线程进行网络请求
new Thread(new Runable()){
    @Override
    public void run(){
        Response<UserInfoModel> response=null;
        try{
           response=call.execute();
        }catch{
           e.printStackTrace();
        }
        //处理服务器返回的数据
    }
}.start();

b.异步:调用Call对象enqueue(),参数是一个回调。

//异步时,框架中已经封装好数据转换、线程切换的操作,无需手动开线程
call.enqueue(new Callback<ResultBean>() {
@Override
public void onResponse(Call<ResultBean> call, Response<ResultBean> response) {
    ResultBean resultBean =response.body();
    CheckShow(resultBean.getCode());
    pbChecking.setVisibility(View.GONE);
    ToastUtilsFixed.show(getApplicationContext(), resultBean.getMsg());
}

    @Override
    public void onFailure(Call<ResultBean> call, Throwable t) {
        pbChecking.setVisibility(View.GONE);
        ToastUtilsFixed.show(getApplicationContext(),"校验手机号失败");
    }
});
  1. 处理服务器返回的数据
    Log.i(“response”,“code:”+response.body().code);//结果为"code:1"

(七)、绘图与动画

动画分为三种:View Animation(视图动画)、Drawable Animation(帧动画)、Property Animation(属性动画)。setDuration(int类型)表示展示多久时间;

一)、View Animation(视图动画)

四种动画效果:平移动画、缩放动画、旋转动画、透明动画;

名称 标签 子类
平移动画 TranslateAnimation
缩放动画 ScaleAnimation
旋转动画 RotateAnimation
透明度动画 AlphaAnimation
  1. 平移动画:

二)、Drawable Animation(帧动画)

三)、Property Animation(属性动画)

(八)、系统硬件相关开发

一)、调用相机和相机权限

Android6.0调用相机相册步骤:
1、Android 6.0需要提供动态申请权限。调用相机拍照,访问SDcard等操作都需要先申请对应的权限

<!-- 用于获取相机使用权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 用于写入缓存数据到扩展存储卡 -->
2、设置生成图片路径(字符串),并使用Intent请求使用相机截图
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  //请求使用相机截图

Android6.0调用相册步骤:
1、 在清单文件添加权限

<!-- 用于读取存储卡中的数据 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

2、在代码中添加请求

Final Intent intent=new Intent(Intent.ACTION_PICK);  //选择数据
intent.setType(“image/*”);    //获取本地所有图片
startActivityForResult(intent,CONSTANTS_SELECT_PHOTO_CODE);
setType接口可以调用图库获取本地图片(“image/*”),调用本地联系人、音频(“audio/*”)、视频(“video/*”)

本地获取图片顺序:
1、 获取权限
2、 (相册)获取图片请求

Intent intent=new Intent(Intent.ACTION_PICK);intent.setType(“image/*”);
startActivityForResult(intent,1)
(相机)调用相机
Intent intent=new Intent(MediaStore.ACTION_PICK);intent.setType(“image/*”);

3、(相册)获取图片路径(uri)通过inputStream转化换成bitmap格式()
Android7.0的问题:
Android7.0之后,不能进行直接访问根目录file://URL的操作,否则会直接抛出FileUriEXposedException异常。而Android7.0之前是使用URL方式直接存储剪裁图片

二)、生物识别技术

API23之后开始有指纹识别技术,使用的FingerprintManager,在API28之后则更改为使用BiometriPrompt类,此类是在封装了FingerprintManager类的基础上创建的。此目前生物技术使用最多的是指纹识别技术与面部识别技术。目前较为成熟的是指纹技术。

  1. 指纹识别
    在清单文件中添加指纹权限USE_BIOMETRIC

相关类有FingprintManagerCompat(FingerprintManager|BIometriPrompt),CancellationSignal,CryptoObject。
开启的方式FingprintManagerCmpat.authenticate(FingerprintManagerCompat.CryptoObject crypto,int flags,@Nullable CancellationSinal cancel,@NonNull FingerprintManagerCompat.AuthenticationCallback callback,@Nullable Handler handler);

FingerprintManagerCompat.CryptoObject crypto:(加密类对象)
可以为null,这意味着app无条件信任认证的结果。因此不建议写成null。
实例化较为麻烦。主要使用javax的security接口实现。
int flags:一个标志,默认为0。

CancellationSinal cancel:
可以为null。用户在使用sensor时取消当前的扫描操作。取消之后需要重新创建。
FingerprintManagerCompat.AuthenticationCallback callback:是一个抽象类
不能为null。提供了几个回调方法,包括指纹的识别成功、失败,需要重写。提供的回调方法有
1、 onAuthenticationError(int errMsgId,CharSequence errStirng):在多次指纹识别错误之后调用,或者在用户取消sensor扫描操作时调用
2、 onAuthenticationFailed:指纹有效但无法识别时调用
3、 onAuthenticationHelp(int helpMsgId,CharSequece helpString):验证过程中出现可恢复错误时调用
4、 onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result):指纹识别成功
Handler handler:
可以为null。用于处理会回调事件

(九)、系统API,地图定位

55

(十)、多线程

一)、AsyncTask异步任务(轻量级异步类,抽象类,使用时需实现其子类)

UI线程超过5秒没有响应请求,就会报错CalledFromWrongThreadException
异步使用最多的地方网络操作,图片加载,数据传输。AsyncTask是做做小应用,公司做项目使用更多的是第三方开发框架,比如Volley,OkHttp,android-async-http,XUtils等等,

二)、Handler机制

Android中有两个通信的框架:网络层的通信框架(进程里面的通信框架或网络间的通信框架)handler(android系统自带的)和binder(解决进程间通信的);他们包含了android底层间通信所有知识
Handler解决的是进程内通信(应用内的通信,线程间的通信),Binder是解决进程间通信;应用之间的通信是使用AIDL(其基础是Binder)
Handler运行流程:发送消息流程Handler->sendMessage()->MessageQueue.enqueueMessage()
接收消息流程 Looper.loop()->MessageQueue.next()->handler.hanlerMessage()
应用启动的流程:home中点击应用icon时,launcher->zygote->fork->Jvm(虚拟机)->activityThread.main()。 其中activityThread.main()中调用了Looper.prepareMainLooper(),启动了Looper。
一个线程中有多个Handler。
每个线程中只包含一个Looper、一个MessageQueue,一个Looper只对应一个MessageQueue(MessageQueue存取消息,里面有大量的message):Looper中有一个 static final ThreadLoacl sThreadLocal=new ThreadLocal();(ThreadLocal是一个线程的上下文变量,用于存储上下文)。ThreadLocal中有一个静态的类ThreadLocalMap(HashMap 是一个键值对集)

Android为了线程安全。不允许UI线程外的子线程操作UI,但可以通过Hanlder通知通知UI组件更新,还有runOnUiThread()来更新,还有更高级的事务总线。
总体流程:若子线程修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理!
Handler类的引入:
在这里插入图片描述

Handler的执行流程图:
在这里插入图片描述

Handler相关名词
1、UI线程:
主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其相关联的MessageQueue
2、Handler:
发送与处理信息
handler可以让主线程监听子线程发送来的消息
Handler可以定时处理或者分发消息;
还可以添加一个执行的行为在其他线程中执行,

1、 void handleMessage(Message msg):处理消息的方法,通常是用于被重写
2、 sendEmptyMessage(int what):发送空消息
3、 sendEmptyMessageDelayed(int what,long delayMillis):指定延时多少毫秒后发送空消息
4、 sendMessage(Message msg):立即发送信息
5、 sendMessageDelayed(Message msg, long delayMillis):指定延时多少毫秒后发送消息
6、 final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。如果是参数(int what,Object object):除了判断what属性,还需要判断Object属性是否为指定对象的消息

3、Message:
Handler接收与处理的消息对象;用于存放传递的数据;是主线程和子线程传递数据的载体
1)如何使用Message:
1、 初始化Message对象:

Message message=new Message();
Message message=Message.obtain();
Message message=Message.obtainMessager();

2、 向Message中添加数据:

message.what=0;  // what用来保存消息标示的
message.arg1=1;   //arg1和arg2存放整型数据
message.arg2=2;
messafe.obj=”传递的内容”;   //obj是Object类型的任意对象
Bundle bundle=new Bundle();   
bundle.putString(“name”,”张三”);
message.setData(bundle);

3、 获取Message中存储的数据

private Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int flag1 = msg.what;
            int flag2 = msg.arg1;
            int flag3 = msg.arg2;
            String resultMsg = (String) msg.obj;
            Bundle bundle = msg.getData();
            String name = bundle.getString("name");
        }
    };

2)Send方式-【注意事项】:
1、 子线程向主线程中发送空消息时,可以调用方法直接传入what值,并且放入到消息队列中:
2、 Send方式发送消息,需要创建Message对象,封装传递的数据,将Message对象压入消息队列中;
3、 Send方式发送消息后,需要在Handler的 handleMessage(Message)方法中,获取消息并处理;
4、 Send方式定时发送消息和延迟发送消息, 时间的单位是毫秒。

4、MessageQueue:
消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue
5、Looper:
每个线程只有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理
主要用于一个线程循环获取消息队列的消息。
主要是负责管理消息队列,负责消息的出列和入列操作。
6、ThreadLocal – 线程本地变量:
ThreadLocal是一个数据结构,与HashMap类似,可以保存“key,value”键值对,但是它只能保存一个,并且各个线程的数据互不干扰。

该类提供线程局部变量,它不同于一般的,它通常是:与线程关联的私有静态字段,例如用于ID或事物ID。

Hanlder使用:
1、在主线程中使用:
在主线程中,因为系统已经初始化了一个Looper对象,可以直接创建Handler对象,就可以对信息进行发送与处理了

2、在子线程中使用:

三)、继承Thread类

四)、实现Runnable类

五)、HandlerThread

(十一)、Android设计模式

一)、单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。适用应用中某个实例对象需要频繁的访问,应用中每次只会存在一个实例。

  1. 懒汉模式
    使用的时候:TestUtils.getInstance().**;
    public class TestUtils{
        //持有私有静态实例,防止被引用,此处设为null,目的是实现延迟加载
        private static TestUtils testUtils=null;
        private TestUtils() { }//构造方法私有化,防止被实例化
        //懒汉式,静态工程方法,创建实例
        public static TestUtils getInstance(){
            if (testUtils==null){
                testUtils=new TestUtils();
            }
            return testUtils;
        }
}

特点:创建静态实例,并且将其构造方法设置为私有化,在应用开启的时就已经创建好类。
优点:延迟加载,需要的时候才去加载
缺点:线程不安全,在多线程中很容易出现不同步的情况。如在数据库对象进行的频繁读写操作时;
2. 饿汉模式

(十二)、序列化、反序列化

序列化:将对象转化成可以传输的二进制流的过程。最终转化为可以在网络传输或者保存到本地的流,从而进行传输数据
反序列化:从二进制流转化的对象的过程

Java中提供了标准的序列化接口——Serializable;
Android中也提供了序列化接口——Parcelable。
两者相比较,Parcelable相对复杂一些;效率比较高;当数据存储在磁盘上时,不能使用;在外界变化的情况下不能很好的保证数据的持续性。因此尽量使用Serializable

(十三)、状态栏、标题栏、导航栏、系统栏、应用栏的区别

在这里插入图片描述

标题栏(ActionBar)
系统栏(system bar)=状态栏(status bar)+导航栏(navigation bar)
应用栏(app bar):又名操作栏,一般把标题栏设为应用栏

沉浸式状态栏: 指状态栏与标题栏颜色相匹配
隐藏导航栏:指将导航栏都隐藏,去掉下面的黑条
App全屏:状态栏、导航栏都隐藏

一)、第一种透明化状态栏的方法

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M)
{
  getWindow().getDecorView().setSystemUiVisibility(
          View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
              |View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
          getWindow().setStatusBarColor(Color.TRANSPARENT  );
}
setContentView(R.layout.send_activity);

二)、第二种隐藏状态栏与导航栏的方法

 View view =getWindow().getDecorView();

// 表示全屏的意思(隐藏状态栏)  SYSTEM_UI_FLAG_FULLSCREEN;
int i=View.SYSTEM_UI_FLAG_FULLSCREEN;
view.setSystemUiVisibility(i);

// 同时使用以下两种,可以是状态栏和导航栏同时隐藏
// 缺陷是点击屏幕任意地方,就会退出隐藏模式
int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
          | View.SYSTEM_UI_FLAG_FULLSCREEN;
view.setSystemUiVisibility(option);

三)、透明化状态栏与导航栏

View view =getWindow().getDecorView();
 // 隐藏导航栏  View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
 // 应用主体占用系统导航栏空间   View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

 // 下面两个flag结合作用是应用主体内容占用系统状态栏的空间
 // 但是必须再调用window的setStatusBarColor()方法将状态栏设置成透明色
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
          |View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
view.setSystemUiVisibility(option);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
getWindow().setStatusBarColor(Color.TRANSPARENT);
setContentView(R.layout.send_activity);

四)、屏幕沉浸式模式:两种方式。

第一种:在代码写,适用于单个activity页面或者fragment页面

public void onWindowFocusChanged(boolean hasFocus) {
  super.onWindowFocusChanged(hasFocus);
  if (hasFocus && Build.VERSION.SDK_INT >= 19) {
       View decorView = getWindow().getDecorView();
       decorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
 小提示:屏幕横屏可以在清单文件中
        <activity android:name=".MainActivity"
        android:screenOrientation="landscape">
        ...
        </activity>

第二种:在清单文件中添加,适用于多个activity页面使用
1、在values文件夹中的styles.xml中创建style类型

第一种方式:<style name=CustomName” parent=CustomName2></style>
注:CustomName2是有些功能在values中会报错,需要在特定的values-v**中编写
书写格式如第种方式
<style name="AppTheme.StatusTranslate" parent="Theme.AppCompat.Light.NoActionBar">
    <!--状态栏透明并且最外层布局顶格,除非使用android:fitsystem="true"-->
    <item name="android:windowTranslucentStatus">true</item>
</style>

第二种方式:<style name=CustomName>
   <item name="windowActionBar">false</item>
   <item name="windowNoTitle">true</item>
</style>

五)、隐藏标题栏(ActionBar):

ActionBar bar=getActionBar();()
bar.hide();//隐藏标题栏
Bar.show();//显示标题栏

六)、Flag的值需要了解以下几种情况:

1、SYSTEM_UI_FLAG_FULLSCREEN
   隐藏状态栏,主体向上偏移,但在手动下拉会重新显示状态栏并清除该flag。
   View.SYSTEM_UI_FLAG_FULLSCREEN |View.SYSTEM_UI_FLAG_LAYOUT_STABLE
   限制主体位置保持不变,状态栏留白
2、SYSTEM_UI_FLAG_HIDE_NAVIGATION
隐藏导航栏,主体向下偏移,由于导航栏太重要了,所以只要和Activity进行任何交互都会重新显示导航栏,并清除该flag和SYSTEM_UI_FLAG_FULLSCREEN。
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
限制主体位置保持不变,导航栏留白
SYSTEM_UI_FLAG_LAYOUT_STABLE
保持内容主体位置不变,不随着Systembar的隐藏显示而偏移
3、SYSTEM_UI_FLAG_IMMERSIVE
沉浸模式:只能和SYSTEM_UI_FLAG_HIDE_NAVIGATION结合使用。
简单交互不会重新显示导航栏
4、SYSTEM_UI_FLAG_IMMERSIVE_STICKY
沉浸模式:只能和SYSTEM_UI_FLAG_FULLSCREEN或SYSTEM_UI_FLAG_HIDE_NAVIGATION结合使用。
下拉状态栏位置可以短暂显示状态栏和导航栏,然后再次隐藏。
5、SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
主体占据全部屏幕,但不隐藏状态栏,这里的layout可以理解为内容主体
6、SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
主体占据全部屏幕,但不隐藏导航栏,这里的layout可以理解为内容主体
7、SYSTEM_UI_FLAG_LAYOUT_STABLE
这个Flag确实有点难以理解,唯一读懂的是在各种flag切换的时候能保持内容主体的稳定性。
如果你不想flag变换的时候内容主体上下偏移,就需要设置SYSTEM_UI_FLAG_LAYOUT_STABLE。
8、SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
浅色状态栏模式:对应于图标变深色,防止浅色背景导致状态栏看不清,不设置是深色模式

 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

五、Android开发基础知识 的相关文章

随机推荐

  • 我的世界启动器怎么更改java_我的世界启动器Java路径怎么设置?

    本文是历趣手游专区小编为诸位我的世界PC端玩家带来的我的世界启动器Java路径如何设置攻略 希望诸位我的世界玩家会喜欢 我的世界java路径设置攻略 1 首先我们要确保电脑中已经下载并安装好了最新的java 如果没有的话 我们直接在网上搜索
  • 计算机设备问题代码43,win10系统提示由于该设备有问题windows已将其停止(代码43)的修复方案...

    有关win10系统提示由于该设备有问题windows已将其停止 代码43 的操作方法想必大家有所耳闻 但是能够对win10系统提示由于该设备有问题windows已将其停止 代码43 进行实际操作的人却不多 其实解决win10系统提示由于该设
  • jmeter及jdk的环境变量配置

    jmeter是apache公司基于java开发的一款开源压力测试工具 其内部原理都是源于java的运行 并支持多种外部插件用于接口及性能测试 最主要的还是开源免费 在安装jmeter前必须配置jdk环境 jdk下载地址 https www
  • vsCode中conda activate失败的解决办法

    首先贴上报错信息 无法加载文件 C Users 13623 Documents WindowsPowerShell profile ps1 因为在此系统上禁止运行脚本 CommandNotFoundError Your shell has
  • git网址访问加载超时速度慢

    git来重置密码 再点击git网站无法打开怎么解决 首先我们应该要明白gitl本身访问就比较慢 所以我们需要登录时候需要借用github但有时候会出现访问速度特别慢的情况因此咱们需要修改配置 借用最新的ip地址来自增强访问github网站的
  • Android系统中数据库应用

    1 设置策略中的数据库 frameworks base packages SettingsProvider src com android providers settings DatabaseHelper java 2 sqlite3操作
  • 【Firefly入门教程】firefly、MySQL和Memcached共同使用

    coding utf8 firefly MySQL和Memcached共同使用 from firefly dbentrust dbpool import dbpool from firefly dbentrust memclient imp
  • 1116:打印零与奇偶数

    题目描述 假设有这么一个类 class ZeroEvenOdd public ZeroEvenOdd int n 构造函数 public void zero printNumber 仅打印出 0 public void even print
  • 什么是文件服务器

    文件服务器是一种器件 它的功能就是向服务器提供文件 在计算机局域网中 以文件数据共享为目标 需要将供多台计算机共享的文件存放于一台计算机中 这台计算机就被称为文件服务器 文件服务器具有分时系统管理的全部功能 能够对全网统一管理 能够提供网络
  • 自己如何重装系统_重装系统方法汇总

    系统崩溃或者蓝屏后 只能重装系统才能解决问题 电脑安装系统方法很多 除费时麻烦现在很少应用的完全安装方法外 常用克隆安装 其方法又分为 硬盘安装 适用于进行过系统备份的熟练用户 U盘安装 适用于有一定电脑操作能力的基础用户 和光盘安装 适用
  • HuggingFace学习3:加载预训练模型完成机器翻译(中译英)任务

    加载模型页面为 https huggingface co liam168 trans opus mt zh en 文章目录 整理文件 跑通程序 测试预训练模型 拆解Pipeline 逐步进行翻译任务 整理文件 首先下载模型所需的全部文件 h
  • 手动搭建python环境

    手动安装python3 9 1 wget https www python org ftp python 3 9 1 Python 3 9 1 tgz tar xf Python 3 9 1 tgz cd Python 3 9 1 sudo
  • 试题 算法提高 拦截导弹

    资源限制 内存限制 256 0MB C C 时间限制 1 0s Java时间限制 3 0s Python时间限制 5 0s 问题描述 某国为了防御敌国的导弹袭击 发展出一种导弹拦截系统 但是这种导弹拦截系统有一个缺陷 虽然它的第一发炮弹能够
  • Docker入门之安装Tomcat

    目录 1 Docker 中安装 Tomcat 1 1 查看 Docker Hub 上的 Tomcat 镜像 1 2 从 Docker Hub 上拉取 Tomcat 镜像 1 3 查看本地镜像列表中拉取的 Tomcat 镜像 2 创建容器并运
  • EM算法及其改进算法

    EM算法及其改进算法 搬运 EM算法笔记一 讲了基础的EM算法 EM算法笔记二 讲述了EM的改进算法 讲得很清晰 EM算法笔记三 不同应用场景的阐述
  • JavaScript实现跳跃游戏的贪婪方法的算法

    JavaScript实现跳跃游戏的贪婪方法的算法 跳跃游戏是一种常见的游戏类型 其中玩家需要控制角色进行跳跃操作以避开障碍物并达到目标 在这篇文章中 我们将使用JavaScript实现跳跃游戏的贪婪算法 该算法能够根据当前情况做出最优的跳跃
  • SpringFramework核心技术一(IOC:使用ICO容器)

    使用容器 这ApplicationContext是高级工厂的接口 能够维护不同bean及其依赖项的注册表 使用该方法T getBean String name Class requiredType 可以检索bean的实例 一 在Applic
  • 稀疏贝叶斯学习【Sparse bayesian learning】

    参考文献 An Empirical Bayesian Strategy for Solving the Simultaneous Sparse Approximation Problem 传统图像恢复 例如用Gaussian 噪声模型 TV
  • 基于ROS环境的相机标定教程

    一 参考资料 ROS学习 利用电脑相机标定 二 安装usb cam驱动包 usb cam ROS Wiki GitHub ros drivers usb cam A ROS Driver for V4L USB Cameras usb ca
  • 五、Android开发基础知识

    android系统一共分为四层 application java应用程序 Framework java框架或系统服务 Library 本地框架或本地服务又称为Native Android Runtime java运行环境 Linux Ker