那些你所不知道的Android小知识(持续更新)

本文主要是收录一些人们可能经常会忽略,但又挺重要的Android方面的小知识。有推荐的也可以在下方留言,大家一起进步呀!

目录:
1.Button, ImageButton和ImageView的区别
2.Activity和Fragment的生命周期,并且讲一下他们之间的关系(先后顺序)
3.Service两种启动方式的区别
4.为什么系统不建议在子线程访问UI
5.如果在android应用程序中需要发送短信,那么需要在AndroidManifest.xml文件中增加什么样的权限
6.layout中创建的.xml 起名范围
7.Android 手机安装的应用都是以apk的形式来进行的。他实质上是个压缩包。在apk包中都没有包含的文件是
8.Android版本分布
9.像素密度对应的Android资源文件夹
10.如果Android应用程序需要设置屏幕方向为横屏方式显示,那么需要在AndroidMainfest.xml文件增加哪种权限
11.Toast的提示时长
12.进程重要性及销毁顺序
13.编写Aidl文件时,需要注意的地方
14.Intent可以传递哪些类型的数据
15.线程、Looper、MessageQueue、Handler对应的数量关系
16.Uri的使用场景
17.ServiceConnection接口的onServiceConnected()方法的触发条件
18.ANR产生时, 系统会生成一个跟踪日志文件,它的具体路径及名称是什么
19.图片占用内存问题
20.style和theme的区别
21.使用SimpleAdapter作为 ListView的适配器,行布局中支持的控件
22.Android系统对哪些对象提供了资源池
23.android的自动恢复功能
24.RemoteView在哪些功能中使用
25.SharedPreference.Editor的apply和commit方法异同
26.Android应用启动黑白屏问题
27.Android 为每个应用程序分配的内存大小是多少
28.如何让点击事件和长按事件不同时响应
29.GLSurfaceView的特性
30.多个Android应用怎么运行在同一个虚拟机中
31.讲一下EventBus与广播的区别
32.ViewStub标签的注意事项
33.onDestroy与finish的区别

2019-7-6

1.Button, ImageButton和ImageView的区别
  • 属性方面:
    ① Button有text属性,其他没有;
    ② ImageButton和ImageView有src属性,Button没有;
    ③ 三个都有background属性。

  • 继承方面:
    ① Button继承TextView
    ② ImageButton继承ImageView
    ③ImageView继承View

  • 显示方面
    ① Button和ImageButton有按钮的样式,ImageView没有
    ② ImageView显示圆角图片的时候,ImageButton显示不了,因为它有自己默认的背景

图片.png

2019-7-7

2.Activity和Fragment的生命周期,并且讲一下他们之间的关系(先后顺序)
两者对应流程图.jpg

(1)Activity生命周期
onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy

(2)Fragment生命周期
onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetach

(3)关系(Activity用A表示,Fragment用F表示)

Activity中onCreate相关代码
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.framelayout,new MyFragment());
transaction.commit();

A.onCreate -> F.onAttach -> F.onCreate -> F.onCreateView -> F.onStart -> A.onStart -> A.onResume -> F.onResume -> 跳转到其他Activity时 -> F.onPause -> A.onPause -> F.onStop -> A.onStop -> 点击返回键 -> A.onRestart -> F.onStart -> A.onStart -> A.onResume -> F.onResume -> 再按一次返回键 -> F.onPause -> A.onPause -> F.onStop -> A.onStop -> F.onDestroyView -> F.onDestroy -> F.onDetach -> A.onDestroy

流程图:

图片.png

跳转到其他Activity时

图片.png

点击返回键

图片.png

再按一次返回键

图片.png

xml文件中直接引用fragment的跳转情况和上方是一样的。其中activity的xml文件是如下的:




   

   

3.Service两种启动方式的区别

(1)使用startService启动

  • 生命周期:onCreate -> onStartCommand -> onDestroy
  • 一旦服务开启就跟调用者(开启者)没有任何关系了。
  • 开启者退出了,开启者挂了,服务还在后台长期的运行。
  • 开启者不能调用服务里面的方法。

(2)使用bindService启动

  • 生命周期:onCreate -> onBind -> onUnBind -> onDestroy
  • 该方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。
  • 绑定者可以调用服务里面的方法。
  • 常用于Service和Activity间通信。

2019-8-1

4.为什么系统不建议在子线程访问UI

系统不建议在子线程访问UI的原因是,在Android中的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态。那为什么系统不对UI控件的访问加上锁机制呢?原因有两个:其一,加上锁会让UI访问的逻辑变的复杂;其二,锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。所以在Android系统中最简单而且高效的方法就是采用单线程模型来处理UI操作。(但是子线程并非说完全不能更新UI哦,符合一定的条件也是可以的)

2019-8-5

5.如果在android应用程序中需要发送短信,那么需要在AndroidManifest.xml文件中增加什么样的权限

答案:android.permission.SEND_SMS

< !-- 阅读消息-->
< uses-permission android:name="android.permission.READ_SMS"/>
< !-- 写入消息-->
< uses-permission android:name="android.permission.WRITE_SMS" />
< !-- 接收消息 -->
< uses-permission android:name="android.permission.RECEIVE_SMS" />

6.layout中创建的.xml 起名范围

答案:(a~z) (0~9)( _ )

7.Android 手机安装的应用都是以apk的形式来进行的。他实质上是个压缩包。在apk包中都没有包含的文件是

答案:包含了开发过程中的各种资源文件、代码类文件包classes.dex、AndroidManifest.xml等,不包含src下的.java文件,因为他们已经被编译了。

8.Android版本分布
版本分布.png
9.像素密度对应的Android资源文件夹
(密度:ldpi-120,mdpi-160,hdpi-240,xhdpi-320,xxhdpi-480,xxxhdpi-640).png

其他单位说明:
px(像素):屏幕上的点
in(英寸):长度单位
mm(毫米):长度单位
pt(磅):1/72英寸
dp(与密度无关的像素):一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp = 1px
dip:与dp相同,多用于android/ophone示例中

sp(与刻度无关的像素):与dp类似,但是可以根据用户的字体大小首选项进行缩放。
在屏幕密度为160,1dp=1px=1dip;当屏幕密度为240时,1dp=1dip=1.5px.

10.如果Android应用程序需要设置屏幕方向为横屏方式显示,那么需要在AndroidMainfest.xml文件增加哪种权限

答案:android.permission.SET_ORIENTATION

11.Toast的提示时长

toast只能设置提示时长为 2s3.5s ,其它的值都无效,API的文档虽然写的第三个参数是时间,但是Framework里作了重定义,限定了 2s和3.5s 这两个值 ,对应 Toast.LENGTH_SHORT和Toast.LENGTH_LONG(他们是NotificationManagerService.java里面的两个静态int常量),实现方式在NotificationManagerService.java的scheduleTimeoutLocked()这个函数里。

12.进程重要性及销毁顺序

重要性依次是:前台进程,可见进程,服务进程,后台进程和空进程;所以销毁的顺序是逆方向。

13.编写Aidl文件时,需要注意的地方

①接口名和aidl文件名相同。
②接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。
③Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、 CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作 为参数或返回值,自定义类型必须实现Parcelable接口。
④自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。
⑤在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。
⑥Java原始类型默认的标记为in,不能为其它标记。

14.Intent可以传递哪些类型的数据

①8种基本数据类型及其数组
②String(String实现了 Serializable )/CharSequence实例类型的数据及其数组
③实现了Parcelable的对象及其数组
④实现了 Serializable 的对象及其数组

2019-8-6

15.线程、Looper、MessageQueue、Handler对应的数量关系

一个线程只会有一个Looper对象;
一个线程只会有一个MessageQueue对象;
一个线程可以有多个Handler对象,但共用一个MessageQueue。

16.Uri的使用场景

(1)调web浏览器
Uri myBlogUri = Uri.parse(" http://xxxxx.com ");
Intent intent = new Intent(Intent.ACTION_VIEW, myBlogUri);

(2)地图
Uri mapUri = Uri.parse("geo:38.899533,-77.036476");
Intent intent = new Intent(Intent.ACTION_VIEW, mapUri);

(3)调拨打电话界面
Uri telUri = Uri.parse("tel:100861");
Intent intent = new Intent(Intent.ACTION_DIAL, telUri);

(4)直接拨打电话
Uri callUri = Uri.parse("tel:100861");
Intent intent = new Intent(Intent.ACTION_CALL, callUri);

(5)卸载
Uri uninstallUri = Uri.fromParts("package", "xxx", null);
Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUri);

(6)安装
Uri installUri = Uri.fromParts("package", "xxx", null);
Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

(7)播放
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");
Intent intent = new Intent(Intent.ACTION_VIEW, playUri);

(8)调用发邮件
Uri emailUri = Uri.parse("mailto:[email protected]");
Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri);

(9)发邮件
Intent intent = new Intent(Intent.ACTION_SEND);
String[] tos = { "[email protected]" };
String[] ccs = { "[email protected]" };
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, "body");
intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
intent.setType("message/rfc882");
Intent.createChooser(returnIt, "Choose Email Client");

(10)发短信
Uri smsUri = Uri.parse("tel:100861");
Intent intent = new Intent(Intent.ACTION_VIEW, smsUri);
intent.putExtra("sms_body", "yyyy");
intent.setType("vnd.android-dir/mms-sms");

(11)直接发邮件
Uri smsToUri = Uri.parse("smsto://100861");
Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri);
intent.putExtra("sms_body", "yyyy");

(12)发彩信
Uri mmsUri = Uri.parse("content://media/external/images/media/23");
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "yyyy");
intent.putExtra(Intent.EXTRA_STREAM, mmsUri);
intent.setType("image/png");

17.ServiceConnection接口的onServiceConnected()方法的触发条件

答案:bindService()方法执行成功同时onBind()方法返回非空IBinder对象(不能仅仅是bindService()方法执行成功后,因为Android官方文档里面对于onBind()方法的解释,最后一句 if you don't want to allow binding, you should return null.如果你不希望你的服务被绑定,那么你应该返回null。实际测试的结果确实如此,如果onBind()方法返回null,那么onServiceConnected将不会被调用。)

18.ANR产生时, 系统会生成一个跟踪日志文件,它的具体路径及名称是什么

答案:data/anr/traces.txt

19.图片占用内存问题
① 每个像素占用多少 byte ?

Bitmap.Config 有四种枚举类型。
通道类型后数字表示每个通道占的大小

ARGB_8888:每个通道 8 bit * 4个通道 = 32 bit = 4 byte,即每个像素点占用4字节
ARGB_4444:同理,2 字节
RGB_565:RGB 3个通道分别是 5 、6 、5 ,加起来 16 bit,也就是 2 个 byte
ALPHA_8:只有 A 通道,占 8 bit,1 个byte
② 被加载的图片有多少像素点呢?

各资源文件对应屏幕密度(每英寸的像素点)

图片.png

注意:实际加载的像素不一定等于原图像素,如资源目录屏幕密度与目标机器不匹配,将按比例缩放

③ 总结

公式=类型占用字节 x 图片原像素宽 x(目标机器屏幕密度/资源文件夹代表屏幕密度)x 图片原像素高 x(目标机器屏幕密度/资源文件夹代表屏幕密度)
4 * 72 * (320/480) * 72 * (320/480)= 9216 byte

这也是为什么在开发中往往尽可能配齐多个资源文件夹,在高分别率的机器上使用低分辨率资源文件夹的资源有可能导致占用内存翻倍,甚至翻数倍

④ 注意:

查阅博客可能有文章提到,内存占用 = bitmap 宽 * bitmap 高 * 类型占用字节(默认是 4)这个公式针对的是bitmap的大小,指的是屏幕上的大小(bitmap.width,bitmap.height),不是指的原图大小,比如一张 50 * 50的图,当它在屏幕上显示是150 * 150时,它的内存占用就是150 * 150 * 4(不考虑view因为view在项目里大部分时候都是定长定宽的)无论原图大小多大,它最后在屏幕中呈现的大小即bitmap.width,bitmap.height才是我们计算的标准。

20.style和theme的区别
① 都可以减少重复属性设置
② 属性

style和theme本质上就是同一个东西,xml格式完全相同,只是我用在activity上我就叫他theme,我用在view上我就叫他style。唯一的区别就是style里头控制的各个属性了,某些属性是只有针对Activity才能生效的(你view有标题栏吗有状态栏、导航栏吗?但是反过来Activity内部却有一个继承自View的Decorview) 。所以style可以作用在activity上,但是theme却不能反过来作用在view上。
(一个TextView的style中定义了textColor属性,TextView本身也设置textColor属性,那么TextView本身定义的优先级较高)

21.使用SimpleAdapter作为 ListView的适配器,行布局中支持的控件

答案: 实现Checkable接口的控件(需要重写的方法有setChecked、isChecked和toggle,比如CheckBox, CheckedTextView, CompoundButton, RadioButton, ToggleButton)、TextView、ImageView 。

22.Android系统对哪些对象提供了资源池

答案:Message和AsyncTask。
① 为Message提供了消息池,有静态方法Obtain从消息池中取对象;
② 为AsyncTask提供了线程池,池里默认提供(核数+1)个线程进行并发操作,最大支持(核数 * 2 + 1)个线程,超过后会丢弃其他任务。
(Thread默认不提供资源池,除非使用线程池ThreadPool管理;
每个Looper创建时创建一个消息队列和线程对象,也不是资源池;)

23.android的自动恢复功能

答案:android的自动恢复功能能够完成恢复备份设置和数据来重新安装程序。

24.RemoteView在哪些功能中使用

答案:AppWidget和Notification。(RemoteView顾名思义就是远程View,它表示的是一个View结构,它可以在其他进程中显示,为了跨进程更新它的界面,RemoteViews提供了一组基础的操作来实现这个效果。)

2019-8-26

25.SharedPreference.Editor的apply和commit方法异同

apply没有返回值而commit返回boolean表明修改是否提交成功
apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘。因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
apply方法不会有任何失败的提示。 (由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。)

2019-8-30

26.Android应用启动黑白屏问题

原因:
当我们在启动一个应用时,系统会去检查是否已经存在这样一个进程,如果没有则系统对应用进行冷启动,系统和APP本身都有很多工作需要做。首先系统的服务会先检查startActivity中的intent的信息,然后再去创建进程,最后才是执行启动Acitivy的操作。黑白屏的问题,就是在这段时间内产生的。
系统在绘制页面加载布局之前,首先会初始化窗口(Window),而在进行这步操作时,系统会根据我们设置的Theme来指定它的Theme主题颜色。Window布局的顶层是DecorView,StartingWindow显示一个空DecorView,我们在Style中的设置就决定了显示的是白屏还是黑屏。

解决方法 :
黑白屏是根据我们设置的Theme来决定了,那我们就可以直接从启动页的Theme入手,我们给启动页设置一个全屏的背景图片,这样就不用显示默认的主题颜色了,这样就能避免白屏问题了。

附:
冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。
热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。

27.Android 为每个应用程序分配的内存大小是多少

google原生OS的默认值是16M,但是各个厂家的OS会对这个值进行修改。

28.如何让点击事件和长按事件不同时响应

在同时绑定两个事件的情况下,
① 如果先点击的是短按事件没问题,自然触发不到长按事件。
② 如果先触发的是长按事件(默认return false),return false的话代表当前事件需要继续向下传递所以短按事件就被响应了,return true的话代表当前有能力消费掉该事件,阻止事件向下传递,短按事件就不会被触发了。

2019-9-2

29.GLSurfaceView的特性

定义:
GLSurfaceView是一个视图,继承至SurfaceView,它内嵌的surface专门负责OpenGL渲染。
特性:
① 管理一个surface,这个surface就是一块特殊的内存,能直接排版到android的视图view上。
② 管理一个EGL display,它能让opengl把内容渲染到上述的surface上。
③ 用户自定义渲染器(render)。
④ 让渲染器在独立的线程里运作,和UI线程分离。
⑤ 支持按需渲染(on-demand)和连续渲染(continuous)。
⑥ 一些可选工具,如调试。

30.多个Android应用怎么运行在同一个虚拟机中

可以安排两个应用共享同一 Linux 用户 ID,在这种情况下,它们能够相互访问彼此的文件。 为了节省系统资源,可以安排具有相同用户 ID 的应用在同一 Linux 进程中运行,并共享同一 VM(应用还必须使用相同的证书签署)。

2019-9-8

31.讲一下EventBus与广播的区别
区别.png

2019-10-28

32.ViewStub标签的注意事项

① ViewStub标签只能加载一次,之后ViewStub对象会被置为空。换句话说,某个被ViewStub指定的布局被加载后,就不能再通过ViewStub来控制它了。所以当需要再运行时不止一次显示和隐藏某个布局时,不能使用ViewStub来实现。
② ViewStub只能用来加载一个布局文件,而不是某个具体的View。当然也可以把View写在某个布局文件中,如果是这样的话,还是使用visibility属性较好。
③ ViewStub中不能嵌套Merge标签。

2020-2-17

33.onDestroy与finish的区别

(1)onDestroy:它是activity生命周期的一个方法,它会在activity被销毁之前调用。
(2)finish:它用于结束一个activity的生命周期,系统是会马上将该activity移除出栈,finish会执行onDestroy方法,但是并不一定会立即执行onDestroy方法。

你可能感兴趣的:(那些你所不知道的Android小知识(持续更新))