Android 面试:常见问题总结,android艺术开发探索

@Override

protected void onRestart() {

super.onRestart();

mEditText.setText(mString);

}

二、生命周期方法中系统在做什么和我们应该做什么

onCreate: 在这里创建界面,做一些数据的初始化工作。

onStart: 到这一步变成用户可见不可交互的。

onResume: 变成和用户可交互的。

(在activity 栈系统通过栈的方式管理这些个

Activity的最上面,运行完弹出栈,则回到上一个Activity)

onPause: 到这一步是可见但不可交互的。

1.系统会停止动画等消耗CPU的事情

2.从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候

你的程序的优先级降低,有可能被系统收回。

3.在这里保存的数据,应该在onResume里读出来,

注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动。

onstop: 变得不可见 ,被下一个activity覆盖了。

onDestroy: 这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法

或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,

如果你有一个Progress Dialog在线程中转动,请在onDestroy里把他cancel掉,

不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。

onPause,onstop, onDestroy 三种状态 下Activity都有可能被系统干掉。

  • 为了保证程序的正确性,你 要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般是数据库 )。

  • 实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制 [Handler,Message]来处理多线程和界面交互的问题。

三、如何让Activity变成一个窗口

  1. 在AndroidManifest.xml 中设置Activity的主题

android :theme="@android:style/Theme.Dialog"

android:theme="@android:style/Theme.Dialog"

android:theme="@android:style/Theme.Translucent"

android:theme="@android:style/Theme.Translucent"

类似这种Activity的属性可以在android.R.styleable 类的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类 android.R.styleable.

四、Service使用场景和生命周期

1. 概念

Service不能与用户交互,不能自己启动,运行在后台。

如果我们退出应用时,Service进程并没有结束,它仍然在后台运行。

2. 使用场景
  • 当我们想音乐在后台播放,就得Service,否则就听不到歌。

  • 当应用的数据是通过网络获取的,不同时间段的数据是不同的

我们可以用Service在后台定时更新,而不用每打开应用的时候在去获取。

3. Service生命周期

Service的生命周期比Activity简单,它只继承了onCreate(),onStart(),onDestroy()三个方法。

  • 第一次启动Service时,先后调用了onCreate() , onStart()

  • 停止Service时,则执行onDestroy()

  • 如果Service已经启动,当我们再次启动Service时,不会在执行onCreate(),而是直接执行onStart()

五、JNI 的书写步骤

  1. 声明 native 方法

  2. 编译该java类

  3. 使用 javah ? jni java 类名 生成扩展名为.h的头文件

  4. 使用 C/C++实现本地方法

  5. 将 C/C++编写的文件生成动态连接库

这里以HelloWorld为例:

class HelloWorld {

// 声明native方法,并且不能实现

public native void displayHelloWorld();

/* 加载动态库, 参数“hello”是动态库的名字

  • 可以这样理解:我们的方法displayHelloWorld()没有实现,

  • 但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化

  • 这里一般是以static块进行加载

*/

static {

System.loadLibrary(“hello”);

}

public static void main(String[] args) {

new HelloWorld().displayHelloWorld();

}

}

六、JNI 调用中考虑的问题

1. java和c是如何互通的?
  • 不能互通的原因主要是 数据类型 的问题。

  • 但jni解决了这个问题,例如c文件中的 jstring 数据类型就是 java传入的String对象 ,经过jni函数的转化就能成为c的 char*

对应数据类型关系如下表:

| Java 类型 | 本地c类型 | 说明 |

| — | — | — |

| boolean | jboolean | 无符号,8 位 |

| byte | jbyte | 无符号,8 位 |

| char | jchar | 无符号,16 位 |

| short | jshort | 有符号,16 位 |

| int | jint | 有符号,32 位 |

| long | jlong | 有符号,64 位 |

| float | jfloat | 32 位 |

| double | jdouble | 64 位 |

| void | void | N/A |

2. 如何将java传入的String参数转换为c的char*,然后使用?
  • java 传入的String参数,在c文件中被jni转换为jstring的数据类型

  • 在c文件中声明 char* test,然后

test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);

  • 注意:test使用完后,通知虚拟机平台相关代码无需再访问:

(*env)->ReleaseStringUTFChars(env, jstring, test);

3. 将c中获取的一个char*的buffer传递给java?
  1. 这个char*如果是一般的字符串的话,作为 string 传回去就可以了。

  2. 如果是含有’/0’的buffer,最好作为 bytearray 传出,

因为可以制定copy的length,如果copy到string,可能到’/0’就截断了。

有两种方式传递得到的数据:

  1. 在jni中直接new一个byte数组,然后调用函数(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);将buffer的值copy到bytearray中,函数直接return bytearray就可以了。

  2. return 错误号,数据作为参数传出,但是java的基本数据类型是传值,对象是传递的引用,所以将这个需要传出的byte数组用某个类包一下,如下:

class RetObj

{

public byte[] bytearray;

}

这个对象作为函数的参数retobj传出,通过如下函数将retobj中的byte数组赋值便于传出。代码如下:

jclass cls;

jfieldID fid;

jbyteArray bytearray;

bytearray = (*env)->NewByteArray(env,len);

(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);

cls = (*env)->GetObjectClass(env, retobj);

fid = (*env)->GetFieldID(env, cls, “retbytes”, “[B”]);

(*env)->SetObjectField(env, retobj, fid, bytearray);

4. 不知道占用多少空间的buffer,如何传递出去呢?
  • 在 jni 的c文件中new出空间,传递出去。

  • java的数据不初始化,指向传递出去的空间即可。

七、Android中的动画有哪几类,它们的特点和区别是什么?

  1. Tween动画:使视图组件移动、放大、缩小以及产生透明度的变化

给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。

  1. Frame动画:传统的动画方法,通过顺序的播放排列好的图片来实现。

  2. 属性动画:真正的改变属性。

八、Handler机制的原理

Andriod 提供了 Handler 和 Looper 来满足线程间的通信。

  1. Looper : 一个线程可以产生一个Looper对象,管理此线程里的MessageQueue(消息队列)。

  2. Handler : 构造Handler对象来与Looper沟通,

如push新消息到MessageQueue里,或者接收Looper从MessageQueue取出的消息。

  1. MessageQueue : 消息队列,用来存放线程放入的消息。

  2. 线程 : UI线程通常就是主线程,程序启动时会替它建立一个MessageQueue。

九、mvc模式的原理以及在Android中的运用

松耦合,组件的重用。

  1. view:视图层,一般采用xml文件进行界面的描述,也可以使用javascript+html等的方式作为view层。

  2. controller:一般指Acitvity,所以不要在acitivity中数据操作等耗时操作的代码,要通过activity交割model业务逻辑层处理。

  3. model:对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。

十、介绍下Android的数据存储方式

  1. 使用SharedPreferences存储数据;

  2. 文件存储数据;

  3. SQLite数据库存储数据;

  4. 使用ContentProvider存储数据;

  5. 网络存储数据;

Android 中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。

十一、介绍下ContentProvider是如何实现数据共享的

ContentProvider:为存储和获取数据提供统一的接口,可以在不同的应用程序之间共享数据。

无论数据的来源是什么,ContentProvider都会认为是一种表,然后把数据组织成表格。

  1. 定义一个继承ContentProvider的类

  2. 实现ContentProvider的所有方法 (query、insert、update、delete、getType、onCreate)

  3. 在AndroidMinifest.xml中进行声明

十二、如何启用Service,如何停用Service

  1. 通过调用Context.startService()启动,调用Context.stopService()结束,

startService()可以传递参数给Service.

  1. 第二种方式是通过调用Context.bindService()启动,调用Context.unbindservice()结束

这种方式可以通过ServiceConnection访问Service。

  • 在Service每一次的开启关闭过程中,只有onStartCommand()可被多次调用(通过多次startService调用),

  • 其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。

十三、注册广播接收器有几种方式,这些方式有何优缺点?

Android中,不同 进程之间 传递信息要用到广播。

方式1. 在Manifest.xml中注册广播

是一种比较推荐的方法,不需要手动注销广播。

(如果广播未注销,程序退出时可能会出错),范例代码:

<receiver android:name = “.MyBroadcastReceiver”

上面两个android:name分别是 广播名广播动作名

如果要自己发送一个广播,在代码中为:

Intent i = new Intent(“com.zhuanghongji.broadcastreceiver.test”);

sendBroadcast(i);

广播就发出去了,然后是接收。

新建一个类,继承至BroadcastReceiver,也可以建一个BroadcastReceiver的实例,然后得写onReceive()方法,实现如下:

protected BroadcastReceiver mEvtReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (action.equals(“com.zhuanghongji.broadcastreceiver.test”)) {

//Do something

}

}

};

方式2. 接在代码中实现,但需要手动注册注销

通过IntentFilter设置action,使用 registerReceiver() 方法进行注册。

IntentFilter filter = new IntentFilter();

filter.addAction(“com.zhuanghongji.broadcastreceiver.test”);

registerReceiver(mEvtReceiver, filter);

// 这时注册了一个recevier ,名为mEvtReceiver,

// 然后同样用上面的方法以重写onReceiver,

// 最后在程序的onDestroy中要注销广播,实现如下:

@Override

public void onDestroy() {

super.onDestroy();

unregisterReceiver(mPlayerEvtReceiver);

}

十四、请谈谈Android引入广播机制的用意

1. 解答
  • Android系统中的广播是广泛用于 应用程序之间通信 的一种手段。

类似于事件处理机制,不同的地方就是广播的处理是系统级别的事件处理过程(一般事件处理是控件级别的)。在此过程中仍然是离不开Intent对象,理解广播事件的处理过程,灵活运用广播处理机制,在关键之处往往能实现特别的效果。

  • 在Android 中如果要发送一个广播必须使用sendBroadCast(Intent intent) 向系统发送对其感兴趣的广播接收器中。

  • 使用广播必须要有一个intent 对象必设置其action动作对象使用广播必须在配置文件中显式的指明该广播对象。

  • 每次接收广播 都会重新生成一个接收广播的对象,在 BroadCast中 尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理.

补充:

2. BroadcastReceiver的生命周期:

这里写图片描述

大意为:如果一个广播处理完onReceive 那么系统将认定此对象将不再是一个活动的对象,也就会finished掉它。

3. 如何在一个广播接收器中处理多个动作呢?
  • 同样的你必须在 Intent-filter 里面注册该动作,可以是系统的广播动作也可以是自己需要的广播。

  • 之后你之需要在onReceive 方法中,通过 intent.getAction() 判断传进来的动作即可做出不同的处理,不同的动作。

小结:

  • 在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。

  • 使用广播必须要有一个intent 对象必设置其action动作对象

  • 使用广播必须在配置文件中显式的指明该广播对象

  • 每次接收广播都会重新生成一个接收广播的对象

尾声

评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。

有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。

一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。

由于文章篇幅问题复制链接查看详细文章以及获取学习笔记链接:前往我的GitHub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值