原文链接:https://blog.csdn.net/lzq520210/article/details/79481086
首先声明一下,以下部分答案是我自己答得,有不对的地方,大家可以在评论区改正,共同成长。
多点面试题
1、解决大图片加载卡顿问题 先使用默认图占位,加载小图 然后再加载大图
2、长图压缩
3、经纬度 实时定位 耗电 为什么不在某一时刻 去请求位置 经纬度是真的吗 百度和高德怎么转换
4、版本更新为什么使用服务 没有直接下载 当时使用服务 是在服务中开启的子线程下载,然后将为了将进度发送的通知栏中
5、解决android7.0不能正常更新问题 api是24
1.声明provider
2.FileProvider Uri apkUri =FileProvider.getUriForFile(context, "cn.doolii.usershopping.fileprovider", updateFile);
3.放到intent中 startActivity
6、强制更新怎么实现的
7、自定义view实现打标签怎么做的 自定义view继承Relativelayout 自定义一个view继承button 有几个属性 方向 标签内容 id等 重写onTouch事件 触摸位置获取到xy轴 addview
8、使用ImageLoader加载并缓存图片以及圆头像展示 加载获取bitmap canvas.drawRoundRect 画圆角矩形
9、解决ScrollView与Viewpager和ListView冲突问题 动态计算listview的高度 然互设置 首先从listviewgetAdapter 遍历adapter中的view 测量高度 累加 然后设置给listview Viewpager 也是动态设置
10、首次打开App实现展示动态广告页面 我们的做法 直接加载图片 大小200k以内 先显示默认图片 加载成功在替换 另一个方案 可以下载到本地 下次打开再展示 或者
11、用百度定位实现地推人员的定位及签到。 到时间点 点击签到按钮 然后进行签到 传经纬度
美图面试
1、支付
2、同步锁 自旋锁
3、ANR什么场景遇到
4、性能优化做过哪方面
5、内存泄露
6、安装包瘦身
7、二分法
8、handler机制
9、线程池怎么使用
10、极光推送
出门问问面试
1、下拉加载 自己实现 怎么实现
2、单例模式 加同步锁 怎么加 锁是什么
3、打开ac的时候动画怎么搞的 context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.push_right_in,R.anim.pull_left_out);
4、动画几种模式
帧动画 1首先在res/drawable文件夹下添加图片 2新建frame_anim.xml <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true" >
<item
android:drawable="@drawable/img00"
android:duration="50"/>
3 imageView.setBackgroundResource(R.drawable.frame_anim);
animationDrawable = (AnimationDrawable) imageView.getBackground();
animationDrawable.start();
补间动画 1anim下创建xml
<?xml version="1.0" encoding= "utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees= "0"
android:toDegrees= "360"
android:duration= "1000">
</rotate>
2Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate);
ivGirl.startAnimation(animation);
属性动画
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 0f);
//沿x轴放大
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 2f, 1f);
//沿y轴放大
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 2f, 1f);
//移动
ObjectAnimator translationXAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0f, 200f, 0f);
//透明动画
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f);
AnimatorSet set = new AnimatorSet();
//同时沿X,Y轴放大,且改变透明度,然后移动
set.play(scaleXAnimator).with(scaleYAnimator).with(animator).before(translationXAnimator);
//都设置3s,也可以为每个单独设置
set.setDuration(3000);
set.start();
5、android与js交互
1mWebView.getSettings().setJavaScriptEnabled(true);
2mWebView.addJavascriptInterface(new JSInterface(), "hgj");
3//js接口类
private class JSInterface {
@JavascriptInterface
public void acceptUrl(String imgUrl) {//此方法是将android端获取的url返给js
}
@JavascriptInterface
public void fnUrl(String s) {
//js可以调用此方法 将s值传给android端,然后android端进行相应的操作,此参数可以是任意类型的
}
@JavascriptInterface
public void fnId(String received){
//android 调用js js会回传参数
Log.i("received--","---"+received);
}
}
4 mWebView.loadUrl("javascript:acceptUrl('" + url + "')");
5 js给android传数据 wv.loadUrl("javascript:fnId()");
6、activity的启动模式 a打开a 栈里是什么样的 standard singleTask singleTop singleInstance 单任务模式 使用场景 第一个a onResume onPause onStop 第二个a生命周期从头开始
如果是signleTop a的生命周期
singleInstance 使用场景:电话拨打界面,Calendar或是DeskClock的闹钟, 收发邮件的Activity, NFC 等
7、单例优缺点
既能够在需要时才初始化单例,又能保证线程安全,且单例对象初始化后调用getInstance不进行同步锁
public class Singleton{
private static Singleton sInstance = null;
private Singleton(){
}
public void doSomething(){
//这是你的业务代码
}
public static Singleton getInstance(){
if(sInstance == null){
synchronized (Singleton.class){
if(sInstance == null){
sInstance = new Singleton();
}
}
}
return sInstance;
}
缺点:(1)单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。
(2)单例对象如果持有Context,那么很容易引发内存泄露,此时需要注意传给单例对象的Context最好是Application Context。
9、斐波那契数列
//使用递归方法实现斐波那契数列
public static int feibonaci1(int n){
if(n==0){return 0;}
if(n==1){return 1;}
return feibonaci1(n-1)+feibonaci1(n-2);
}
10、递归为什么慢
递归效率低是函数调用的开销导致的。函数调用之前需要做许多工作,比如准备函数内局部变量使用的空间、搞定函数的参数等 把某些递归写成尾递归
11、SharedPreferences 的commit和apply的区别
public void SaveData() {
//指定操作的文件名称
SharedPreferences share = context.getSharedPreferences(SILENAME, MODE_PRIVATE);
SharedPreferences.Editor edit = share.edit(); //编辑文件
edit.putInt("age", 22); //根据键值对添加数据
edit.putString("name", "LJie");
edit.commit(); //保存数据信息
}
public void LoadData() {
//指定操作的文件名称
SharedPreferences share = getSharedPreferences(SILENAME, MODE_PRIVATE);
tv1.setText("作者:"+share.getString("name", "信息为空..."));
tv2.setText("年龄:"+share.getInt("age", 0));
}
commit是原子提交到数据库,所以从提交数据到存在Disk中都是同步过程,中间不可打断。
apply方法的原子操作是原子提交的内存中,而非数据库,所以在提交到内存中时不可打断,之后再异步提交数据到数据库中,因此也不会有相应的返回值。
所有commit提交是同步过程,效率会比apply异步提交的速度慢,但是apply没有返回值,永远无法知道存储是否失败。
在不关心提交结果是否成功的情况下,优先考虑apply方法。
12、弱引用 软引用 区别
弱引用 WeakReference 随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收。要获取对象时,同样可以调用get方法
软引用 SoftReference 当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法
WeakReference一般用来防止内存泄漏,要保证内存被虚拟机回收,SoftReference多用作来实现缓存机制(cache);
13、LRU三级缓存 内存 硬盘 网络
14、大图片处理 10000*1000
会oom 其实是给options的options.inJustDecodeBounds = true; // 设置为true,不将图片解码到内存中
图片长宽压缩:
BitmapFactory的decodeByteArray()、decodeFile()、decodeResource()
这些方法中都会传入一个BitmapFactory.Options实例化对象,通过这个对象,可以更改一些加载图片的设置
如果将options.inJustDecodeBounds设置为true,在解码过程中就不会申请内存去创建Bitmap,返回的是一个空的Bitmap,但是可以获取图片的一些属性,例如图片宽高,图片类型等等。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 设置为true,不将图片解码到内存中
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
// 图片高度
int imageWidth = options.outWidth;
// 图片宽度
String imageType = options.outMimeType;
为了避免OOM的异常,在加载图片到内存之前,会先检查图片的尺寸
质量压缩
public static void compressImageToFile(Bitmap bmp,File file) {
// 0-100 100为不压缩
int options = 100;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
尺寸压缩
public static void compressBitmapToFile(Bitmap bmp, File file){
// 尺寸压缩倍数,值越大,图片尺寸越小
int ratio = 2;
// 压缩Bitmap到对应尺寸
Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio, bmp.getHeight() / ratio, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect rect = new Rect(0, 0, bmp.getWidth() / ratio, bmp.getHeight() / ratio);
canvas.drawBitmap(bmp, null, rect, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
result.compress(Bitmap.CompressFormat.JPEG, 100 ,baos);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
设置图片的采样率,降低图片像素
public static void compressBitmap(String filePath, File file){
// 数值越高,图片像素越低
int inSampleSize = 2;
BitmapFactory.Options options = new BitmapFactory.Options();
//采样率
options.inSampleSize = inSampleSize;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, 100 ,baos);
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
15、高德地图和百度地图经纬度转换
地球坐标 (WGS84)
国际标准,从专业GPS 设备中取出的数据的坐标系
国际地图提供商使用的坐标系
火星坐标 (GCJ-02)也叫国测局坐标系
中国标准,从国行移动设备中定位获取的坐标数据使用这个坐标系
国家规定: 国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。
百度坐标 (BD-09)
百度标准,百度 SDK,百度地图,Geocoding 使用
(本来就乱了,百度又在火星坐标上来个二次加密)
火星坐标系:
iOS 地图(其实是高德)
Gogole地图
搜搜、阿里云、高德地图
百度坐标系:
当然只有百度地图
WGS84坐标系:
国际标准,谷歌国外地图、osm地图等国外的地图一般都是这个
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
*
* @param lat
* @param lon
*/
public static double[] gcj02_To_Bd09(double lat, double lon) {
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
double[] gps = {tempLat,tempLon};
return gps;
}
某大型互联网面试 面试了三轮 都是安卓技术面 两个半小时
一面
1、ac的启动模式 standard singleTop singleTask singleInstance(闹钟 打电话)
2、handler原理 主线程子线程looper问题
一个线程只有一个messageQueue? 两个handler可以共用一个messageQueue? 一个Thread 只有一个looper 多个handler
多个handler可以共用一个messagequeue 怎么区分
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
enqueueMessage()方法里面有一个msg.target = this;这句话就是重点,就是说我们通过sendMesasge(msg)一层一层的传递消息,最后这个msg.target=this就是把当前的这个handler标记给这个当前我们发送的msg,然后再把这个打好标记的信息添加到消息队列中。
3、HandlerThread怎么回事
new HandlerThread的Looper和ActivityThread的Looper不是同一个。HandlerThread自带一个looper对象, HandlerThread.getLooper()方法即可获得该HandlerThread的looper对象
4、IntentService 原理自动开子线程 执行耗时操作
5、自定义控件 自定义属性先在res\values目录下创建attrs.xml,定义自己的属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView">
<!--声明MyTextView需要使用系统定义过的text属性,注意前面需要加上android命名-->
<attr name="android:text" />
<attr name="mTextColor" format="color" />
<attr name="mTextSize" format="dimension" />
</declare-styleable>
</resources>
在布局文件中,使用属性(注意引入我们应用程序的命名空间,这样在能找到我们包中的attrs):
<com.example.openxu.myview.MyTextView
android:layout_width="200dip"
android:layout_height="100dip"
openxu:mTextSize="25sp"
android:text="我是文字"
openxu:mTextColor ="#0000ff"
android:background="#ff0000"/>
在构造方法中获取属性值:
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
String text = ta.getString(R.styleable.MyTextView_android_text);
int mTextColor = ta.getColor(R.styleable.MyTextView_mTextColor, Color.BLACK);
int mTextSize = ta.getDimensionPixelSize(R.styleable.MyTextView_mTextSize, 100);
ta.recycle(); //注意回收
Log.v("openxu", “text属性值:"+mText);
Log.v("openxu", "mTextColor属性值:"+mTextColor);
Log.v("openxu", "mTextSize属性值:"+mTextSize);
}
6、recyclerView怎么使用 怎么加header 我们使用itemtype
7、ui过渡渲染 什么情况导致 怎么处理 开发者选项 打开过渡渲染按钮
8、性能优化
apk瘦身 analyze --run inspection by name --输入unused resource 第三方sdk
启动优化
内存优化 内存泄露 leakcanary 怎么确定代码有泄露 monitor MAT 怎么使用 怎么查找哪里泄露了
ui优化
耗电优化 什么时候耗电
http请求(GZIP压缩)
json数据解析(json解析效率主要是解析耗时),大量的数据解析
3.数据库读写操作
4.SD卡读写操作
5.程序的执行的timer定时器(例如IM中的心跳包,用系统的Alarm优化)
6.网络切换(wifi会比手机的数据移动网络更加省电)
9、百度地图和高德地图怎么转换经纬度
10、java线程锁 有哪些 syncronize 修饰静态方法和非静态方法的区别 静态锁是类。class 非静态锁是对象 如果让一个静态方法和非静态方法产生互斥 用同一个锁 可以做到
11、git 使用流程 git pull git add . git commit -m"" git push git branch git checkout git reset --hard^
12、pull和pull --rebase
—rebase 并不会产生一个commit提交,而是会将你的E commit附加到D commit的结尾处。在看commit log时,不会多出你所不知道的commit出来。其实此处的F commmit是无意义的,它只是一个merge commit。而且这里面的message里面的branch日后也不存了,这些分支都会被清除掉。
13、分渠道打包
14、MultiDex 一个dex文件不能超过65536方法
使用方法 三步
buildgradle中配置multiDexEnabled true
defaultConfig {
multiDexEnabled true
}
dependencies添加依赖 compile 'com.android.support:multidex:1.0.0'
自定义app继承MultiDexApplication
15、动画分几种
帧动画
res dawable中 加入xml文件 《animation-list <item drawable=""
img.set
补间动画
属性动画
16、android与js交互
@Javascript 有什么漏洞
JavaScript一种解释型语言,其执行原理是边解释边运行,JavaScript与一些服务器脚本语言(如ASP、PHP)以及编译型语言(如C、C++)不同,其源代码可以轻松被任何人获取到
解决:不把此类敏感信息直接存储进页面内的js和ajax请求响应内容中就可以解决这类问题
17、个人优势 (会吹牛逼 算吗 哈哈)
18、项目埋点
19、大图片卡顿怎么处理
20、scrollview和listview冲突怎么解决 重写listview 或者动态就算listview每一个item的高度,然后设置listview的总高度
二面
21、webview返回相关
canGoback 有问题吗 怎么解决的
因重定向无法正常goBack()
22、app广告页是怎么实现的 有几种方案
23、分渠道打包 gradle配置渠道包 360加固
24、java sleep wait区别
25、图片加载框架 imageloader glide Picasso 区别
imageloader 比较老的框架, 稳定, 加载速度适中, 缺点在于不支持GIF图片加载, 使用稍微繁琐, 并且缓存机制没有和http的缓
存很好的结合, 完全是自己的一套缓存机制(完整大小).
Picasso 使用方便, 一行代码完成加载图片并显示, 框架体积小,
缺点在于不支持 GIF, 并且它可能是想让服务器去处理图片的缩放, 它缓存的图片是未缩放的, 并且默认使用
ARGB_8888 格式缓存图片, 缓存体积大.
glide可以说是 Picasso 的升级版, 有 Picasso 的优点, 并且支持 GIF 图片加载显示, 图片缓存也会自动缩放, 默认使用
RGB_565 格式缓存图片, 是 Picasso 缓存体积的一半.
26、推送 个推 极光 如何根据个人信息推消息 别名 推送消息 后台可以直接发送推送吗 推送到达率多少?能保证多大的到达率?
27、json解析是怎么回事,怎么就把json字符串转成对象了
28、哪些对象需要序列化 用intent传值 对象做存储
29、哪些对象需求混淆 哪些对象不能被混淆
#---------------------------------默认保留区---------------------------------
-
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.view.View
-keep public class * extends android.preference.Preference
-keep class android.support.** {*;}
30、觉得自己在项目中哪块擅长
31、RelativeLayout 中间放一个Button 怎么做 在Button 加入centerInParent=“true” RelativeLayout的居中是不起作用的,在父布局RelativeLayout中加入gravity属性是不可行的
32、hashmap底层怎么实现 为什么为什么设计 key-value结构 哈希表 怎么实现的 哈希冲突怎么解决
三面
33、插件化
34、安卓从哪个版本开始使用的art模式
35、art dalvik 区别
Dalvik Android 4.4 及其以下平台使用的虚拟机;
ART Android4.4以上平台使用的虚拟机技术;
android5.0正式使用art虚拟机
36、对kotlin的理解
37、查看我的csdn博客
38、你对加班什么态度
39、如何安抚手下
40、怎么学习
41、怎么看我们公司
领主科技面试
1、23 是安卓6.0 24是安卓7.0
2、如何区分只主项目 还是依赖的第三方 apply plugin: 'com.android.application' apply plugin: 'com.android.library'
3、横屏竖屏
android:configChanges 不写 重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
android:configChanges="orientation|keyboardHidden" 只会执行onConfigurationChanged方法
4、安卓5.0与6.0区别
动态权限
ContextCompat.checkSelfPermission(context,Manifest.permission.CALL_PHONE)!= PackageManager.PERMISSION_GRANTED
ActivityCompat.requestPermissions(context,permissions,requestCode);
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults[i]== PackageManager.PERMISSION_GRANTED)
}
安卓7.0
Uri imageUri = Uri.fromFile(file);
报错FileUriExposedException
使用FileProvider
第一步:在manifest清单文件中注册provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.jph.takephoto.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
exported:要求必须为false,为true则会报安全异常。
第二步:指定共享的目录
第三步:使用FileProvider
Uri imageUri = FileProvider.getUriForFile(context, "com.jph.takephoto.fileprovider", file);//通过FileProvider创建一个content类型的Uri
5、退出app的方式
方式一 android.os.Process.killProcess(android.os.Process.myPid()) //获取PID
System.exit(0); //常规java、c#的标准退出法,返回值为0代表正常退出
方式二 ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);
am.restartPackage(getPackageName());
方式三 把所有ac 添加到集合中 循环finish退出 System.exit(0);
方式四 广播 注册广播 发送广播 统一finish掉
6、服务启动
startService() stopService()或stopSelf() oncreate onStartCommand onDestroy
bindService() unBindService() onCreate onBind onunbind ondestroy
7、Activity与Service的数据交流
a到s start intent传
s到a 1广播 2当Activity和Service绑定时,可以通过Binder来链接Service和Activity,通过Binder来返回绑定的Service来获取Service对象内部的数据。
8、AIDL
9、ContentProvider
10、NDK
下载ndk开发工具包
配置环境变量
local.properties中配置NDK路径 ndk.dir=C\:\\ndk\\android-ndk-r13b
在gradle.properties中配置
android.useDeprecatedNdk=true
1.写native代码用于调用c代码
public class JNI {
static {
System.loadLibrary("Hello");
}
/*
* 定义native方法
* 调用c代码对应的方法
* */
public native String sayHello();
}
2.编译动态链接库
在build.gradle中
defaultConfig {
applicationId "www.basketi.cn.basketball.ccalljavademo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
ndk{
moduleName ("Hello");
abiFilters "armeabi", "armeabi-v7a", "x86"
}
ndk{
ldLibs "log"
}
}
3.加载动态链接库
static {
//加载动态链接库
System.loadLibrary("Hello");
}
4.写对应的c代码
java中native去调用c代码
给含有native方法的类生成头文件,如JNI类,然后根据头文件中的方法,写对应的c代码
11、http和https区别
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
未完待续,仅以我最近的经历,分享给大家,希望可以帮助到你们!
---------------------
Android高级进阶必备篇
Android高级进阶必备篇
Android APP全方位性能调优
Android APP全方位性能调优
微信小程序与Hybrid混合开发
微信小程序与Hybrid混合开发
需要免费学习资料的可以关注我的主页或者
我的CSDN:https://blog.csdn.net/weixin_44109213/article/details/85105880
网友评论