当前位置:   article > 正文

五、Android开发基础知识_安卓开发

安卓开发

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
  • 2
  • 3
  • 4
  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属性配合使用)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

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

特效方法有:

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  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同上
@PathURL缺省值;所有网址中参数(URL的问号前面)同上
@URLURL设置值同上

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
  • 2
  • 3
  1. 在清单文件AndroidManifest.xml中注册权限;
<uses-permission android:name="android.permission.INTERNET"/>
  • 1
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  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注解
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("URL") 
//设置网络请求的Url地址,注意以要以斜线(代表根目录)结尾
                .addConverterFactory(GsonConverterFactory.create()) 
//设置数据解析器,这里表示用的是JSON解析返回值
                .build();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 生成接口对象
    由于是interface不是class,无法直接调用内部方法,需要利用已创建的Retrofit对象去生成代理的接口对象。
CheckPhone是第四步创建的接口名
CheckPhone checkService=retrofit.create(CheckPhone.class);
  • 1
  • 2
  1. 调用接口方法返回Call对象
sendCheckPhone是第四步创建的接口中的方法,phone是RequestBody类型的变量
Call<ResultBean> call=checkService.sendCheckPhone(phone);
  • 1
  • 2
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  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" />
<!-- 用于写入缓存数据到扩展存储卡 -->
  • 1
  • 2
  • 3
2、设置生成图片路径(字符串),并使用Intent请求使用相机截图
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  //请求使用相机截图
  • 1

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

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

2、在代码中添加请求

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

本地获取图片顺序:
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/*”);
  • 1
  • 2
  • 3
  • 4

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();
  • 1
  • 2
  • 3

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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");
        }
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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;
        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

特点:创建静态实例,并且将其构造方法设置为私有化,在应用开启的时就已经创建好类。
优点:延迟加载,需要的时候才去加载
缺点:线程不安全,在多线程中很容易出现不同步的情况。如在数据库对象进行的频繁读写操作时;
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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

 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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

第一种:在代码写,适用于单个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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
 小提示:屏幕横屏可以在清单文件中
        <activity android:name=".MainActivity"
        android:screenOrientation="landscape">
        ...
        </activity>
  • 1
  • 2
  • 3
  • 4
  • 5

第二种:在清单文件中添加,适用于多个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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

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

六)、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
浅色状态栏模式:对应于图标变深色,防止浅色背景导致状态栏看不清,不设置是深色模式

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/235513
推荐阅读
相关标签
  

闽ICP备14008679号