1、10个基本简单的linux
mkdir 创建文件夹
rmdir 删除文件夹
rm 删除文件
touch 创建文件
cat 查看文件
find查找目录
mv 移动(修改)文件
cp 拷贝文件
cd 切换当前目录
tail 查看文件尾部
ls 列出文件清单
reboot重启
ps 查看系统进程
2、adb命令
adb device 查看连接计算机的设备
adb reboot 重启设备
adb reboot bootloader 刷机模式
adb logcat 查看log
adb kill-server 终止进程服务
adb start-server 重启进程服务
adb install xxx.apk安装apk
adb unstall xxx.apk 卸载apk
adb connect ip地址 连接设备
adb shell kill [pid] 杀死进程
adb shell ps 查看进程
adb shell ls 列出目录下的文件夹
adb logcat -c 清除log缓存
3、ANR(Application not Responding) 如何避免?
将耗时的操作,比如:访问网络、Socker通信、大量查询SQL语句都放到子线程中去,通过handle.sendMessage、runonUITread、AsyncTask等方式更新UI。
4、一条最长的短信息约占多少个byte?
国内三大运营商通常情况下中文70、英文160个。包括标点
5、如何判断是否有SD卡:Environment.getExternalStorageState().equals(MEDIA_MOUNTED)
6、Android程序与Java程序的区别:Android程序用android sdk开发,java程序用 java sdk开发。Android程序引用了大部分的Java SDK.
7、启动应用后,改变系统语言,应用的语言会改变么
一般是不会的,只有重启应用才能改变应用语言,除非应用做了国际化处理。
8、介绍下adb、ddms、aapt的作用:
adb:(Android debug bridge)Android调试桥
ddms:(Dalvik DeBug Monitor Service)程序执行查看器(dalvik调试监视服务)
aapt:Android sdk中提供的一个小工具:可以查看、创建、更新ZIP格式的文档附件
9、ddms和traceview的区别:ddms是一个程序执行查看器,在里面可以看见线程和堆栈等信息,traceview是程序性能分析器。
PS:traceview是Android平台特有的数据采集和分析工具。
10、Activity:四大组件之一,是Context的子类,通常一个用户交互界面对应一个activity。
Activity的生命周期:
onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy() 、onRestart()
保存Activity的状态:
重写onSaveInstanceState()方法,接受一个Bundle类型的参数,可以将状态存储到Bundle对象中,当重启activity调用它onCreate()方法时,Bundle将作为实参传递给onCreate()
横竖屏切换时Activity的生命周期:
不设置Activity的android:configChanges时,切屏会重新调用各个生命周期。切横屏会执行一次,竖屏两次
设置android:configChanges=“orientation”时,切屏也还会调用各个生命周期,切横、竖屏时只会执行一次
设置android:configChanges=“orientation|keyboardHidden”时,不会重新调用各个生命周期,只会执行onConfigurationChanged方法
将Activity设置成窗口的样式:
在Manifest中将主题设置成Dialog样式
如何退出Activity?如何安全退出已调用多个Activity的Application?
(1) 一般情况下,用户按back键就可以退出Activity,直接调用finish().
(2) 记录打开的activity,每打开一个就记录下来,在需要退出的时候,关闭每一个activity即可
(3) 发送特定广播,在需要退出的时候,发送一个特定的广播,每个Activity收到广播的时候,关闭即可。
(4)在打开新的Activity时候,使用startActivityforresult,在onActivityResult中处理,递归关闭。
Activity的四种启动模式:
standard:每启动一次都要创建新的实例,不管实例有没有存在。
singleTop:栈顶复用,若在栈顶就不生成新的实例,如果在栈顶就调用onNewIntent复用
singleTask:栈内复用,只要存在栈内就不创建新的实例
singleInstance:单例模式,系统会给该Activity单独创建一个栈
11、Service:四大组件之一
Service是否在main thread中执行,service里是否能执行耗时操作?
默认情况下,service和activity是运行在当前app所在进程的main thread里面,service里面不能执行耗时的操作。特殊情况下,可以在清单文件配置service执行所在的进程,让service在另外进程中执行。
Activity如何绑定service,如何在Activity中启动自己对应的Service?
Activity通过bindService(Intent service,ServiceConnection conn,int flags)跟service绑定,,当绑定成功后service会将代理对象通过回调的形式传给conn,就能拿到Service提供的服务代理对象。
在Activity中通过startService()和bindService()来启动服务,想要获取Service服务对象就通过bindService,若仅仅想要开启一个后台服务,就是要startService()
StartService启动服务,调用者和服务之间没有关联,如果是调用者直接退出没有调用stopService的话,Service一直在后台运行,用BindService启动服务,调用者和服务绑定了,调用者一旦退出,Service也就终止。
Service生命周期:
非绑定模式:onCreate()、onStartCommand()、onDestroy()
绑定模式:onCreate()、onBind()、onUnbind()、onDestroy()
什么是IntentService,有何有点?
IntentService是Service的子类,可以根据需要处理异步请求(表示为Intent)。
Actiivty、Service、Intent的关系:
Activity和Service都是四大组件,都是Context的子类ContextWrapper的子类,Activity负责用户界面的交互和显示,Service负责后台任务的处理,Activity和Service通过Intent传递数据,Intent可看成是通信使者。
12、BroadCastReceiver :四大组件之一,主要用于接收系统或app发送的广播事件。可以进行进程间通信
分为有序广播和无序广播:
无序广播:完全异步,可以被所有广播接收者收到,效率高,但是无法将处理结果传给下个接收者,没有顺序,无法被截断。
有序广播:同步执行的广播,广播发出后同一时间只能有一个广播接收器接收到广播,当优先级高的广播接收器的onReceiver方式运行结束后,广播才会继续,当前广播也可以截断广播,不继续向下传递。
引用广播的用意:
(1)程序间的互通消息
(2)Android的四大组件本质上也就是为了实现移动设备上的MVC架构,可以方便几大组件的信息和数据交互
注册广播的两种方式:
静态注册:在清单文件中为BroadcastReceiver注册,使用
动态注册:在代码中定义并设置好IntentFilter对象,然后在需要注册的地方调用Context.registerReceiver()方法,调用Context.unregisterReceiver()方法取消注册。=>非常驻型广播,跟随Activity生命周期,当程序关闭时,该接收器会被销毁
PS:
BroadcastReceiver生命周期很短,从接收广播创建到onRecrive()方法结束后销毁。
广播接收者中不要做一些耗时操作,会弹出ANR
耗时较长的工作最好在服务中完成
13、ContentProvider:四大组件之一,应用程序之间共享数据的接口
使用方法:自定义一个类继承ContentProvider,然后覆写query、insert、update、delete等方法,第三方可以通过ContentResovler来访问该Provider。
Android的数据存储方式:File存储、ContentProvident存储、SharedPreference存储、SQLiteDateBase存储、网络存储
ContentProvider和sql的区别:ContentProvider屏蔽了数据存储的细节,只需要关心操作数据的uri就可以了,它可以实现不同app之间的共享,sql只能查询本应用下的数据库
说说ContentProvider、ContentResolver、ContentObserver之间的关系:
ContentProvider 内容提供者,用于对外提供数据
ContentProvider.notifyChange(uri)发出消息
ContentResolver:内容解析者,用于获取内容提供者提供的数据
ContentObserver:内容监听器,可以监听数据的改变状态。
ContentResolved.registerContentObserver()监听消息
14、Android中的几种布局文件
线性布局(LinearLayout):水平/垂直
相对布局(RelativeLayout):根据参照物的位置来定位控件的位置
框架布局(FrameLayout):放入的控件都被放到左上的区域。
表格布局(TableLayout):通过表格方式布局(行/列)来布局控件的位置
绝对布局(AbsoluteLayout):采用坐标轴的方式定位控件
约束布局(ConstraintLyout):控件之间存在相应的位置关系。
Padding和Margin区别:
padding站在父view的角度描述问题,规定它里面的内容与这个父view边界的距离,margin是站在自己的角度描述问题,规定自己上下左右的距离。
?
padding是内边距,margin是外边距
15、ListView
ListView如何提高效率
(1)复用ConvertView
(2)自定义静态类ViewHolder
(3)使用分页加载
ListView数据集发生改变后,如何更新ListView?
调用adapter的notifyDataSetChanged方法
如何定位到指定位置:listview.Selection(2)
16、Java中引用类型都有哪些?作用是什么?
几种引用类型:强引用、软引用、弱引用、虚引用
引用类型的作用:使得程序可以更好的控制对象生命周期,帮助缓解和处理内存泄漏的问题。
强引用:必不可少的,Object object=new Object();这是一个强引用,若一个对象具有强引用,垃圾回收器绝不会回收它,哪怕内存控件不足时,java虚拟器宁愿抛出OutOfMemoryError错误,使程序异常终止也不会回收。
软引用:可有可无,当内存空间足够了就不会回收,当内存空间不足时,就会回收这些对象的内存。软引用用来实现内存敏感的高速缓存
弱引用:可有可无,不管内存足够与否,都会回收它的内存,它与软引用的区别在于弱引用的对象具有更短暂的生命周期
虚引用:虚引用并不会决定对象的生命周期,任何时候都可能被垃圾回收。主要用来跟踪垃圾回收的活动。
17、JNI(Java Native Interface)和NDK(Native Development Kit)
JNI作用:使得Java与本地其他语言类(C/C++)交互,它是属于Java的,与Android没有关系。
NDK:Android的一个工具开发包,快速开发C、C++的动态库 。
18、Intent传递:
可以传递哪些数据类型:java的基本数据类型和String以及他们的数组格式,还传递Serializable和Parcelabele接口的对象
19、Serializable和Parcelable的区别:
1.在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Pacelable
2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC(垃圾回收机制)
3.Parcelable不能使用在要将数据存在磁盘上的情况
20、Intent和IntentFilter的区别
Intent代表了Android应用的启动意图,Android应用根据这个Intent来启动指定组件。IntentFilter相当于Intent的过滤器,应用开发完后,需要用IntentFilter告诉Android系统能处理哪些隐式的Intent请求,主要通过data、category、action三方面
21、Fragement
Fragment和Activity间的传值:
Fragment和Activity绑定后,在Fragment中可直接通过getActivity()方法获取到其绑定的Activity对象,这样就能调用到Acitivity的方法了,在Activity中通过如下方式获取到Fragment:FragmentManager manager=getFragmenManager(); Fragment fragment=manager.findFragmentById(id);或者fagment=manager.findFragmentByTag(tag);获取到fragment后就可以调用Fragment的方法。
Fragment生命周期:
创建时会执行的方法:
onAttach():fragment关联activity,在此可与activity通信。
onCreate():系统创建fragment时使用,实例化一些变量,主要是暂停、停止时想保存的数据。
onActivityCreate():在onCreate()执行之后调用,
onCreateView():加载fragment布局
变得可见时会执行:
onStart():Fragment启动时回调,此时Fragment可见
onResume():Fragment进入前台,可再此做一些onpause()或onStop()方法中释放的资源。
进入后台会执行的方法:
onPause():一般指用户离开这个fragment(非销毁),在此可做一些数据存储、动画停止等操作。
onStop():Fragment不可见,可做一些资源释放操作
最后销毁:
onDestroyView():移除布局,销毁相关联的布局,清除与视图相关的资源。
onDestroy():销毁Fragment,回收工作和最终资源释放。
onDetach():activity与fragmnet解除关联
22、如何对Android应用进行内存性能分析:
出现卡顿等原因:
在UI线程中做轻微耗时操作导致
布局Layout过于复杂,无法再16ms内完成渲染
同一时间动画执行的次数过多,导致CPU或GPU负载过多
view过度绘制
View频繁的触发measure、layout
内存频繁触发GC过多
冗余的资源及逻辑导致加载和执行缓慢
ANR
如何进行性能分析:ddms(程序执行查看器)的traceview、heap、allocation tracker等工具
traceview:程序性能分析器
heap:检查代码中可能有内存泄漏的地方
allocation tracker:
什么情况下会导致内存泄漏:
资源释放问题:Context、Cursor、IO流的引用,资源得不到释放
对象内存过大问题:保存了多个耗用内存过大的对象,例如Bitmap、xml文件,造成内存超出限制
static引用资源耗费过多的实例,例如:static Context
线程导致内存泄漏
23、避免OOM(Out Of Memory:内存溢出)异常:分为内存泄漏(申请使用完的内存没有释放)和内存溢出(申请的内存超过了JVM能提供的大小)
图片过大导致OOM时:等比例缩小图片或者是采用软引用及时进行recyle()操作
界面切换导致的OOM:若布局中有背景图之类的,放到onCreate()中去处理,在activity中的onDestroy中drawable.setCallback(null)
查询数据库记得关闭游标
Bitmap对象不再使用时调用recycle()释放内存
24、Android如何捕获未捕获的异常
自定义一个Application,继承Application实现UncaughtExceptionHandler,重写onCreate()和uncaughtException()方法,然后在Manifest中配置该Application
25、Android屏幕适配
dp:dip的缩写,指密度无关的像素(px)
dp适配:
dimens适配:
layout适配
java代码适配
xml布局中weight权重适配
屏幕适配的技巧:
手机自适应情况主要分为:横竖屏的切换(Manifest中配置configChange,然后在activity中重写onConfigChanged方法)、分辨率大小的不同(可设置weight权重设置)
25、AIDL(android interface definition language):
步骤:
服务端:
1.首先创建aidl文件,定义提供的接口
2.创建一个自定义Service继承Service,在里面创建一个类继承刚创建AIDL的Stub类并实现aidl中定义的方法,在onBind返回内部类的方法。
客户端:
3.绑定服务端的Service,使用asInterface()将服务端的Binder对象转换成AIDL接口所属类型。然后调用AIDL中的方法
PS:通过bindService(Intent,ServiceConnect,int)绑定远程服务,bindService中有一个ServiceConnect接口,我们需要覆写onServiceConnected(ConponentName,IBinder)方法,IBinder就是在AIDL中定义的接口。
26、自定义控件
自定义组合控件:自定义组合控件就是把多个控件作为一个整体看待、处理。
自定义view步骤:
1.自定义View的属性:在res/values/下建立一个attrs.xml,在里面定义属性和声明整个样式,然后在布局文件中声明自定义的view,在自定义View的构造方法中获取自定义的样式
2.重写onMeasure()测量view(宽高)和它的内容,每一个measureSpec由一个尺寸(size)和模式(model)
3.重写onDraw()方法,使用Canvas绘制图形
27、Android中的事件处理
Handle机制:Android中的主线程(UI线程)用来创建、更新UI,耗时操作需要在子线程中处理,处理完后为了防止UI处理逻辑混乱,Android只允许主线程修改UI,Handle充当桥梁。
使用步骤:将Handle声明在Activity中,覆写Handle的handleMessage()方法,当子线程调用handle.sendMessage()方法后,handleMessage方法就会在主线程中执行。
PS:
MassageQueue:消息队列,它的内部存储了信息,Looper对象对该线程的MessageQueue进行管理。
Looper:无限循环的方式去查询消息队列中是否有消息。每个线程都有自己的Looper对象,通过ThreadLocal获取当前线程的looper,主线程自动创建Looper对象,而其他线程在使用的时候需要自行创建。通过Looper.prepare()为当前线程创建一个Looper,通过Looper.looper()来开启消息循环。退出looper可通过quit(直接退出looper)和quitSafely(处理消息完后才退出)
Message:MessageQueue中存储的对象。
ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,存储后也只能在指定的线程中获取到数据。通过ThreadLocal来获取到当前线程的Looper
28、事件分发机制
事件分发中的onTouch和onTouchEvent区别,如何使用?
onTouch优先于onTouchEvent执行,若在onTouch中通过返回true将事件消费掉,onTouchEvent将不会再执行。onTouch得到执行需要两个执行条件,一个是onTouchListener的值不能为空,第二是当前点击的控件必须是enable的。
描述一下事件的分发流程:事件收集之后最先传递给Activity,然后依次向下传递,Activity->PhoneWindow->DecorView->ViewGroup->View
如果事件被消费,意味着事件信息传递终止
如果事件没有被消费,事件会回传给Activity,如果Activity也不需要就被抛弃
判断事件是否被消费是根据返回值,而不是根据你是否使用了事件
29、Android数字签名
在Android系统中,所有安装到系统中的应用程序都必有一个数字签名,数字证书的私钥保存在程序开发者手中。用来标识应用程序作者和应用程序之间建立信任关系。
30、Android中的动画
系统动画:
Tween(补间)动画:这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化
Frame(逐帧)动画:传统动画,类似电影
补间动画缺点:
作用对象局限,只能作用在视图View上
没有改变View的属性,只改变视觉效果
动画效果单一
Android 3.0之后加入了属性动画:可以对任意对象的属性进行动画而不仅仅是View。通过AnimatorSet类和xml文件的set标签都可以改变对象的多个属性,实现动画效果。=>AnimatorSet通过before、with、after三个方法组合多个属性动画,with表示与给定动画同时执行,before在给定动画执行前执行,after在给定动画执行之后执行
ObjectAnimator
ValueAnimator:ObjectAnimator的父类,
ObjectAnimator和ValueAnimator传入的都有一个TypeEvaluator类型的参数,只是一个接口,里面也只有一个
31、如何修改Activity进入和退出的动画。
1.定义Activity的主题,在Manifest中给指定的Activity指定theme。
2.覆写overridePendingTransition方法
32、多线程和异步加载
多线程三种方式:
1.new Thread(new Runnable),把run()方法写在线程里
2.让Activity实现Runnable接口,把run方法单独提出来
3.利用线程池ExecutorService接口创建多线程
异步任务三种方式:
1.AsyncTask:doInBackgound()是继承AsyncTask必须要实现的,运行后台,做耗时操作。onPostExecute()在主线程中运行,写开始提示代码。publishProgress()更新进度,给onProgressUpdate()传递参数。onProgressUpdate()在publishProgress()调用完被调用,更新进度
2.Thread的两种方式:(1)public class MyThread extends Thread{},然后调用的时候MyThread.start()。 (2)public class MyRunnable implement Runnable{}, 使用的时候调用new Thread(new MyRunnable()).start()
3.IntentService:具有Service一样的生命周期,提供了后台线程中的异步处理机制,使用public class MyIntentService extends IntentService{}。启动Intent in=new Intent(ServiceActivity.this,MyIntentService.class);startService(in)
33、都使用过哪些框架、平台
EventBus、mob(短信验证)、Retrofit、butterknife、picassio、photoview
34、EventBus:
自定义一个事件类:例如UserBean
要接收消息的页面:
注册:EventBus.getDefault().register(this)
接收消息的方法:onEvent(UserBean bean)
取消注册:EventBus.getDefault().unregister(this)
发送消息的页面:
EventBus.getDefault().post(new UserBean(xxxxx))
35、Context
从Android系统的角度来理解:Context是一个场景,描述的是一个应用程序环境的信息,即上下文,代表与操作系统的交互的一种过程。
从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现,也就是说是它子类
36、RecycleView对于ListView的差异:
LayoutManager管理各种类型的布局
加入Holder来管理布局和布局复用,不同Type的View都要创建各自的Holder
没有现成的ItemClick回调
丰富的数据刷新方法
可自定义分割线
37、如何从网络上加载一张图片显示到界面上
原生方法:使用BitmapFactory.decodeStream(inputString)方法将图片转换成bitmap,然后通过imageview.set ImageBitmap()将图片设置到Imageview中
使用第三方框架:Picasso、ImageLoader等
38、Activity之间的通信方式
startActivityforesult()启动
通过广播形式
Intent跳转时携带数据
数据存储方式:Sharedpreference等
39、Android虚拟机DVM 和java虚拟机JVM的区别
Dalvik基于寄存器,而JVM基于栈,基于寄存器的虚拟机编译时话费时间更短
DVM执行.dex格式的字节码,JVM执行.dass格式的字节码
40、MVC MVP MVVP
MVC:
M:模型层,负责处理数据的加载或者存储
V:视图层,负责界面数据的展示,与用户进行交互
C:控制器层,负责逻辑业务的处理
基本流程:首先视图接收用户的输入请求,然后将请求传递给控制器,控制器再调用模型来处理用户请求。在控制器的控制下,将处理后的结果交给视图进行格式化输出给用户。
MVP:
M:数据层,负责数据的加载或存储
V:视图层,负责界面数据的展示,负责与用户交互
P:中间者,绑定Model层和View层,是Model和View之间的桥梁
MVC和MVP的区别:MVP中的View并不直接使用Model,它们之间的通信是通过Present来进行的,而MVC中View直接从Model中读数据而不是Controller
41、https和http的区别
超文本传输协议Http被用在Web浏览器和网站服务器之间传递信息,以明文方式发送内容,不提供任何方式的数据加密。安全套接字层超文本传输协议HTTPS,在HTTP基础上接了SSL协议,为浏览器和服务器之间的通信加密
42、UDP(用户数据报协议)和TCP(传输控制协议)基本区别
TCP面向连接、传输可靠,用于传输大量数据,速度慢,建立连接需要开销较多
UDP面向非连接,传输不可靠,用于传输少量数据,速度快
43、Socket基本实现原理
基于TCP协议的Socket:
服务端:
1、服务端声明一个ServiceSoket,并指定端口号:ServiceSockt mserviceSoket=new ServiceSocket(8080)
2、调用accept()方法接收数据:Socket socket=mserviceSoket.accept()
3、接收到数据后,通过inputStream读取数据:InputStream inputStream=socket.getInputStream()
4、关闭ServiceSoket:mServiceSocket.close()
客户端:
1、创建一个Socket对象,指定服务器的地址和端口号:Socket socket=new Socket("172.168.10.2",8080)
2、创建一个inputStream读取要发送的文件:InputStream inputStream=new FileInputStream("e://a.txt")
3、获取Socket的OutputStream对象用于发送数据:OutputStream outputStream=socket.getOutputStream()
4、把数据写入到OutputStream对象中:outputStream.write();
5、发送读取的数据到服务端:outputSteam.flush()
基于UDP协议的数据传输
服务端接收客户端实现:
//端口号可以在一个范围内自己定义,表示这个 DatagramSocket 在此端口上监听数据
1、创建一个DatagramSocket对象,并且指定端口号:DatagramSocket socket=new DatagramSocket(8080)
2、创建一个DatagramPacket对象,并指定DatagramPacket对象的大小:DatagramPacket packet=new DatagramPacket(data,data.length)
3、使用DatagramSocket的对象的receive接收数据:socket.recrive(packet)
4、将客户端发送的数据转换成字符串
服务端发送数据实现:
1、创建DatagramSocket,指定端口号:DatagramSocket socket=new DatagramSocket(8080)
2、定义客户端地址:InetAddress address=packet.getAddress()//packet是上面服务端接收客户端实现步骤2的packet
3、定义客户端端口号:int port=packet.getPort();//packet是上面服务端接收客户端实现步骤2的packet
创建DatagramPacket,指定响应数据、数据的长度、客户端地址和客户端端口号:DatagramPacket packet2=new DatagramPacket(data2,data2.length,address,port)
4.通过DatagramSocket.send()方法发送数据:socket.send(packet2)
5.关闭资源:socket.close()
客户端发送数据实现:
1、创建一个DatagramSocket对象,指定监听的端口号:DatagramSocket socket=new DatagramSocket(8088)
2、使用InetAddress.getByName把IP地址转换成网络地址:InetAddress serviceAddress=InetAddress.getByName(10.0.0.12)
3、创建一个DatagramPacket对象,用于发送数据: DatagramePacket packet=new DatagramPacket(data(要发送的数据),data.length(数据长度),serviceAddress(服务端的网络地址),8080(服务端端口号))
4、使用DatagramSocket.send发送数据到服务端:socket.send(packet)
客户端接收服务器返回的数据:
1、创建一个DatagramSocket,指定端口号,要和发送时的socket一致:DatagramSocket socket=new DatagramSocket(8088)
2、创建一个DatagramPacket packet=new DatagramSocket(data,data.length)
3、使用DatagramSocket.receive接收数据:socket.receive()
4、关闭DatagramSocket:socket.close()
44、Andorid系统架构(从上到下)
应用程序层:用Java语言来编写
应用程序框架层:从事Android开发的基础,开发人员可直接使用其提供的组件来进行快速的应用程序开发。
系统运行库层:C++/C库以及Android运行库
Linux内核层:
45、Binder机制原理
从机制、模型角度来说:跨进程通信方式,实现了IBinder接口
从模型结构、组成来说:Binder驱动:连接Service进程、Client进程和ServiceManager的桥梁
从Andorid代码的实现角度来说:Binder机制具体实现原理:注册服务->获取服务->使用服务
46、Android如何加载大图片?对图片进行压缩
针对图片的宽高进行压缩:首先获取加载图片的属性(BitmapFactory.Options、BitmapFactory.decodeResource),然后再缩小图片的长宽来压缩图片
针对图片像素进行压缩,导致图片质量下降
使用Fresco(Fresco是facebook推出的开源项目,该项目主要用来解决Android图片加载的)SimpleDraweeView或ZoomableView
47、LinearLayout(纵只能横用,横只能纵用)的gravity,layout_gravity和weight:
gravity:view本身内容的位置
layout_gravity:控制自己在父元素的位置
weight:置该属性的控件的layout_width="warp_content",很正确.置该属性的控件的layout_width="match_parent",不正确.使用weight权重时,建议将width或height设置为0dp
48、Activity A 跳转到Activity B,生命周期的执行过程
先是ActivityA的onpause()->ActivityB的onCreate()->ActivityB的onStart()->ActivityB的onResume()->ActivityA的onStop()
49、Android中Handler声明非静态对象会发出警告,为什么,非得是静态的?
如果不使用static生命,则会导致内存泄漏。Handler被声明为一个非静态内部类或者匿名类可能会阻止外部类的垃圾回收
50、广播注册后不解除注册会有什么问题? 会出现内存泄漏
51、Dagger通过编译时注解方式,帮我们自动生成创建对象的工厂类。
52、在实际Android项目中用到的设计模式
适配器模式:RecycleView与Adapter
工厂模式:BitmapFactory
观察者模式:EventBus、各种监听器、
单例模式:ActivityManager、FragmentManager
53、单线程中Message、MessageQueue、Looper、Handler之间的关系。
通过Handler获取当前线程中的looper对象,发送消息
Message:线程间交流的信息
MessageQueue:用来存放Handler发布的Message
Looper:执行Message循环
54、Android性能优化
布局优化:减少布局的层级数,删除无用的控件和层级、采用
绘制优化:在view的onDraw中避免大量的操作,比如创建新的局部变量、做耗时操作
内存泄漏优化:(1)静态变量导致的内存泄漏:释放内存。(2)属性动画导致的内存泄漏:在onDestroy中调用animator.cancel()来停止动画。
响应速度优化:避免在主线程中做耗时操作,通过分析data/anr目录下的traces.txt文件定位出ANR原因(ANR日志分析)
ListView和Bitmap优化:(1)listview采用ViewHolder并避免在getView中执行耗时操作,通过列表的滑动状态来控制任务的执行频率。(2)Bitmap主要通过BitmapFactory.Options来根据需要对图片进行采样
线程优化:采用线程池,避免程序中存在大量的Thread
53、Rxjava
作用:实现异步调用
1、链表:线性数据集合,用于表示顺序的数据结构
分为单链表、双链表、循环链表
单链表:每一个节点只指向下一个节点,最后一个指向空
双链表:每个节点有两个指针,一个指向前一个节点,另一个指向后一个节点,最后一个指向null
循环链表:每个节点指向下一个节点,最后一个节点指向第一个节点
2、栈:元素集合,支持两个基本操作:push用于将元素压入栈,pop用于删除栈顶元素
后进先出的数据结构,索引和查找的时间复杂度是O(n),插入和删除的时间复杂度是O(1)
3、队列:元素集合,支持两个基本操作:enqueue用于添加一个元素到队列,dequeue用于删除队列的一个元素
先进先出的数据结构,时间复杂度是索引和查找是O(n),插入和删除是O(1)
4、二叉树:树形数据结构,每个节点最多可以有左右两个子节点
满二叉树:二叉树中的每个节点有0或2个子节点
完美二叉树:二叉树中的每个节点有两个子节点,且所有的叶子结点的深度都一样
完全二叉树:二叉树除了最后一层外其他各层的节点数均达到最大值,最后一层的节点都连续集中在最左边
二叉查找数:任何节点的值都大于等于左子树的值,小于等于右子数的值
5、堆:基于树的满足某些特性的数据结构,分为最大堆和最小堆。在最大堆中,父节点的键值永远大于等于所有子节点的键值,根节点的键值最大。在最小堆中,父节点的键值永远小于等于所有子节点的键值,根节点的键值是最小的。
6、哈希:用于将任意长度的数据映射到固定长度的数据。
1、冒泡排序:通过与相邻元素的比较和交换来把小的数交换到最前面。时间复杂度为O(n^2)
public status void BuddleSort(int array[],int length){
int temp;
for(int i;i1;i++){
for(int j=length-1;j>i;j--){
if(array[j]<array[j-1]){
temp=array[j];
array[j]=array[j-1];
array[j-1]=temp;
}
}
}
}
2、选择排序:在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换。
public status void SelectSort(int array[],int length){
int temp;
for(int i=0;i1;i++)
int minIndex=i;
for(int j=i+1;jif(array[j]<array[minIndex]){
minIndex=j;
}
if(minIndex!=i){
temp=array[i];
array[i]=array[minIndexminIndex];
array[minIndex]=temp;
}
}
}
3、插入排序:在要排序的一组数中,假定前N-1个数已经排好了,现在将第N个数插入到前面的有序数列中,使得这N个数也是排好顺序的。
public status void InsertSort(int array[],int length){
int temp;
for(int i=0;ifor(int j=i+1;j>0;j--){
if(array[j]<array[j-1]){
temp=array[i];
array[i]=array[i-1];
array[i-1]=temp;
}
else{
break;
}
}
}
}