🔥 31、Android 线程间通信有哪几种方式?🔥
1)共享变量(Sharepreferrence)
2)使用管道流(Pipes)
3)handle机制
4)runOnUiThread(Runnable)
5) View.postDelay(Runnable)
6)广播
🔥 32、请解释下 Android 程序运行时权限与文件系统权限的区别? 🔥
文件的系统权限 是由linux系统规定的,只读,读写等。
**运行时权限,**是对于某个系统上的app的访问权限,允许,拒绝,询问。该功能可以防止非法的程序访问敏感的信息。
🔥 33、Framework 工作方式及原理,Activity 是如何生成一个 view 的机制是什么?🔥
Framework是android 系统对 linux kernel,lib库等封装,提供WMS,AMS,bind机制,handler-message机制等方式,供app使用。
简单来说framework就是提供app生存的环境。1)Activity在attch方法的时候,会创建一个phonewindow(window的子类)
2)onCreate中的setContentView方法,会创建DecorView
3)DecorView 的addview方法,会把layout中的布局加载进来。
🔥34、阐述多线程间通信和多进程之间通信有什么不同,分别怎么实现?🔥
一.两者区别
多进程和多线程的主要区别是:线程是进程的子集(部分),一个进程可能由多个线程组成。
多进程的数据是分开的、共享复杂,需要用IPC;但同步简单。
多线程共享进程数据,共享简单;但同步复杂。
(1)多进程进程是程序在计算机上的一次执行活动,即正在运行中的应用程序,通常称为进程。
当你运行一个程序,你就启动了一个进程。
每个进程都有自己独立的地址空间(内存空间),每当用户启动一个进程时,操作系统就会为该进程分配一个独立的内存空间,让应用程序在这个独立的内存空间中运行。
在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态,这便是多进程,也称多任务。现代的操作系统几乎都是多任务操作系统,能够同时管理多个进程的运行。
多任务带来的好处是明显的,比如你可以边听mp3边上网,与此同时甚至可以将下载的文档打印出来,而这些任务之间丝毫不会相互干扰。
1.数据是分开的,共享复杂,同步简单2.占用内存多,切换复杂,CPU利用率低
3.创建销毁复杂,切换复杂,速度慢
4.编程简单,调试简单
5.进程间不会相互影响
6.适应于多核、多机分布 ;如果一台机器不够,扩展到多台机器比较简单
(2)多线程线程是一个轻量级的子进程,是最小的处理单元;是一个单独的执行路径。可以说:线程是进程的子集(部分),一个进程可能由多个线程组成。
线程是独立的。如果在一个线程中发生异常,则不会影响其他线程。它使用共享内存区域。多线程是一种执行模型,它允许多个线程存在于进程的上下文中,以便它们独立执行但共享其进程资源。
1.多线程共享进程数据,共享简单,同步复杂
2.占用内存少,切换简单,CPU利用率高
3.创建销毁简单,切换简单,速度快
4.编程复杂,调试复杂
5.一个线程挂掉将导致整个进程挂掉
6.适应于多核分布
二.使用场景1)需要频繁创建和销毁的优先用线程。
实例:web 服务器,来一个任务建立一个线程,完了就销毁线程。要是用进程,创建和销毁的代价是很高的。
2)需要进行大量计算的优先使用线程。
所谓大量计算,当然就是要消耗很多 cpu,切换频繁了,这种情况线程是最合适的。实例:图像处理、算法处理
3)强相关的处理用线程,弱相关的处理用进程。
4)可能扩展到多机分布的用进程,多核分布的用线程。
5)都满足需求的情况下,用你最熟悉、最拿手的方式。
三.通信方式(1)进程间的通信方式
进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。
1.管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。2.有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
3.信号量(semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也来访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
4.消息队列( messagequeue ) : 消息队列存放在内核中,并由消息队列标识符标识。消息队列克服了信号量传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5.信号 (sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
6.共享内存(shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的通信 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。
7.套接字(socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
2)线程间的通信方式1.锁机制:包括互斥锁、条件变量、读写锁
a.互斥锁: 提供了以排他方式防止数据结构被并发修改。
b.读写锁: 允许多个线程同时读共享数据,而对写操作是互斥的。
c.条件变量: 可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
2.信号量机制(Semaphore):包括无名线程信号量和命名线程信号量.
3.信号机制(Signal)
🔥 35、如何修改 Activity 进入和退出动画?🔥
可以通过两种方式,一是通过定义 Activity 的主题,二是通过覆写 Activity 的 overridePendingTransition 方法。
1:通过设置主题样式
在 styles.xml 中编辑如下代码:
@anim/slide_in_left
@anim/slide_out_left
@anim/slide_in_right
@anim/slide_out_right
2:添加 themes.xml 文件:
@style/AnimationActivity
true
在 AndroidManifest.xml 中给指定的 Activity 指定 theme。
覆写 overridePendingTransition 方法
overridePendingTransition(R.anim.fade, R.anim.hold);
🔥36、Android开发中都使用过哪些框架、平台?🔥
I.EventBus 事件分发机制,由handler实现,线程间通信
II.xUtils->DbUtils,ViewUtils,HttpUtils,BitmapUtils
III.百度地图
IV.volley
V.fastjson
VI.picciso
VII.友盟
VIII.zxing
IX.Gson
🔥37、 简述Android的layout_gravity和gravity的区别?🔥
layout_gravity是根据父布局设置位置的
gravity是根据自身内容设置位置。
🔥 38、 简述Handler ?Handler机制是什么?🔥
Handler是Android官方给我们提供的一套更新UI线程的机制,也是一套消息处理机制,可以通过Handler来处理消息,更新UI等。
然后Handler机制大约是这样的:首先Handler发送一个消息MessageQueue里面,然后通过Looper的loop方法进行无限循环,如果产生了一个新消息,那么就调用handler的handlermessage方法进行余下的操作。
之所以这样做的原因是因为避免多线程并发更新UI线程所产生的问题的,如果我们允许其他子线程都可以更新界面,那么势必会造成界面的错乱(因为没有加锁机制),如果我们加锁,又会影响速度,所以,只能在主线程即UI线程里面更新界面。
🔥39、Android子线程更新UI的方式 ?🔥
css
方式一:Handler和Message
① 实例化一个Handler并重写handlerMessage()方法
private Handler handler = newHandler() {
public void handleMessage(Message msg) {
// 处理消息
super.handleMessage(msg);
switch (msg.what) {
case 1:
button1.setText("点击安装");
break;
case 2:
button1.setText("打开");
break;
}
};
};
css
② 在子线程中获取或创建消息,并使用handler对象发送。
Message msg = handler.obtainMessage();
msg.what = 1;
handler.sendMessage(msg);
方式二:在子线程中直接调用Activity.runOnUiThread(Runnable action)方法
runOnUiThread(new Runnable() {
@Override
public void run() {
// 更新UI的操作
}
});
css
方式三:在子线程中调用View的post()方法
myView.post(new Runnable() {
@Override
public void run() {
// 更新UI
myView.setText("更新UI");
}});
css
方式四:在子线程中调用View.PostDelayed(Runnabe,long)
对方式三对补充,long参数用于制定多少时间后运行后台进程
css
方式五:Handler的post()方法
① 创建一个Handler成员变量
private Handler handler = new Handler();
② 在子线程中调动post()方法
handler.post(new Runnable() {
@Override
public void run() {
// 更新UI
myView.setText("更新UI");
}});
css
方式六:AsyncTask
private class DownloadFilesTask extends AsyncTask
//在这里声明了Params、Progress、Result参数的类型
{
//因为这里不需要使用onPreExecute回调方法,所以就没有加入该方法
//后台线程的目的是更具URL下载数据
protected Long doInBackground(URL... urls) {
int count = urls.length;//urls是数组,不止一个下载链接
long totalSize = 0;//下载的数据
for (int i = 0; i < count; i++) {
//Download是用于下载的一个类,和AsyncTask无关,大家可以忽略他的实现
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * ));//更新下载的进度
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
//更新下载进度
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
//将下载的数据更新到UI线程
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
🔥 40、 简述使用Handler的时候一般会遇到的问题? 🔥
比如说子线程更新UI,是因为触发了checkThread方法检查是否在主线程更新UI,还有就是子线程中没有Looper,这个原因是因为Handler的机制引起的,因为Handler发送Message的时候,需要将Message放到MessageQueue里面,而这个时候如果没有Looper的话,就无法循环输出MessageQueue了,这个时候就会报Looper为空的错误。