Android面试和Java面试总结

来源:互联网 发布:飞行燃料 支持淘宝 编辑:程序博客网 时间:2024/06/03 21:45

参加的Android面试:

Android四大组件:

Activity:

Android 中,Activity 是所有程序的根本,所有程序的流程都运行在Activity 之中,Activity可以算是开发者遇到的最频繁,也是Android 当中最基本的模块之一。在Android的程序当中,Activity 一般代表手机屏幕的一屏。如果把手机比作一个浏览器,那么Activity就相当于一个网页。在Activity 当中可以添加一些Button、Check box 等控件。可以看到Activity 概念和网页的概念相当类似。

  一般一个Android 应用是由多个Activity 组成的。这多个Activity 之间可以进行相互跳转,例如,按下一个Button 按钮后,可能会跳转到其他的Activity。和网页跳转稍微有些不一样的是,Activity 之间的跳转有可能返回值,例如,从Activity A 跳转到Activity B,那么当Activity B 运行结束的时候,有可能会给Activity A 一个返回值。这样做在很多时候是相当方便的。

  当打开一个新的屏幕时,之前一个屏幕会被置为暂停状态,并且压入历史堆栈中。用户可以通过回退操作返回到以前打开过的屏幕。我们可以选择性的移除一些没有必要保留的屏幕,应为Android会把每个应用的开始到当前的每个屏幕保存在堆栈中。

Service:

Service 是android 系统中的一种组件,它跟Activity 的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service 是没有界面的长生命周期的代码。Service 是一种程序,它可以运行很长时间,但是它却没有用户界面。这么说有点枯燥,来看个例子。打开一个音乐播放器的程序,这个时候若想上网了,那么,我们打开Android 浏览器,这个时候虽然我们已经进入了浏览器这个程序,但是,歌曲播放并没有停止,而是在后台继续一首接着一首的播放。其实这个播放就是由播放音乐的Service进行控制。当然这个播放音乐的Service也可以停止,例如,当播放列表里边的歌曲都结束,或者用户按下了停止音乐播放的快捷键等。service 可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD 卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。

  开启service有两种方式:

  (1) Context.startService():Service会经历onCreate -> onStart(如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次 );stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。 注意,多次调用Context.startservice()不会嵌套(即使会有相应的onStart()方法被调用),所以无论同一个服务被启动了多少次,一旦调用Context.stopService()或者stopSelf(),他都会被停止。补充说明:传递给startService()的Intent对象会传递给onStart()方法。调用顺序为:onCreate --> onStart(可多次调用) --> onDestroy。

  (2) Context.bindService():Service会经历onCreate() -> onBind(),onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind -> onDestroyed相应退出,所谓绑定在一起就共存亡了 。


Broadcast:

在Android 中,Broadcast 是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver 是对发送出来的Broadcast进行过滤接受并响应的一类组件。可以使用BroadcastReceiver 来让应用对一个外部的事件做出响应。这是非常有意思的,例如,当电话呼入这个外部事件到来的时候,可以利用BroadcastReceiver 进行处理。例如,当下载一个程序成功完成的时候,仍然可以利用BroadcastReceiver 进行处理。BroadcastReceiver不能生成UI,也就是说对于用户来说不是透明的,用户是看不到的。BroadcastReceiver通过NotificationManager 来通知用户这些事情发生了。BroadcastReceiver 既可以在AndroidManifest.xml 中注册,也可以在运行时的代码中使用Context.registerReceiver()进行注册。只要是注册了,当事件来临的时候,即使程序没有启动,系统也在需要的时候启动程序。各种应用还可以通过使用Context.sendBroadcast () 将它们自己的intent broadcasts广播给其他应用程序。

  注册BroadcastReceiver有两种方式:

  (1)在AndroidManifest.xml进行注册。这种方法有一个特点即使你的应用程序已经关闭了,但这个BroadcastReceiver依然会接受广播出来的对象,也就是说无论你这个应用程序时开还是关都属于活动状态都可以接受到广播的事件;

  (2)在代码中注册广播。

  第一种俗称静态注册,第二种俗称动态注册,这两种注册BroadcastReceiver的区别:

  动态注册较静态注册灵活。实验证明:当静态注册一个BroadcastReceiver时,不论应用程序是启动与否。都可以接受对应的广播。

  动态注册的时候,如果不执行unregisterReceiver();方法取消注册,跟静态是一样的。但是如果执行该方法,当执行过以后,就不能接受广播了。


Content provider:

Content Provider 是Android提供的第三方应用数据的访问方案。

  在Android中,对数据的保护是很严密的,除了放在SD卡中的数据,一个应用所持有的数据库、文件、等等内容,都是不允许其他直接访问的。Andorid当然不会真的把每个应用都做成一座孤岛,它为所有应用都准备了一扇窗,这就是Content Provider。应用想对外提供的数据,可以通过派生ContentProvider类, 封装成一枚Content Provider,每个Content Provider都用一个uri作为独立的标识,形如:content://com.xxxxx。所有东西看着像REST的样子,但实际上,它比REST 更为灵活。和REST类似,uri也可以有两种类型,一种是带id的,另一种是列表的,但实现者不需要按照这个模式来做,给你id的uri你也可以返回列表类型的数据,只要调用者明白,就无妨,不用苛求所谓的REST。

  另外,Content Provider不和REST一样只有uri可用,还可以接受Projection,Selection,OrderBy等参数,这样,就可以像数据库那样进行投影,选择和排序。查询到的结果,以Cursor(参见:reference/android/database/Cursor.html )的形式进行返回,调用者可以移动Cursor来访问各列的数据。

  Content Provider屏蔽了内部数据的存储细节,向外提供了上述统一的接口模型,这样的抽象层次,大大简化了上层应用的书写,也对数据的整合提供了更方便的途径。Content Provider内部,常用数据库来实现,Android提供了强大的Sqlite支持,但很多时候,你也可以封装文件或其他混合的数据。

  在Android中,ContentResolver是用来发起Content Provider的定位和访问的。不过它仅提供了同步访问的Content Provider的接口。但通常,Content Provider需要访问的可能是数据库等大数据源,效率上不足够快,会导致调用线程的拥塞。因此Android提供了一个AsyncQueryHandler(参见:reference/android/content/AsyncQueryHandler.html),帮助进行异步访问Content Provider。

  在各大组件中,Service和Content Provider都是那种需要持续访问的。Service如果是一个耗时的场景,往往会提供异步访问的接口,而Content Provider不论效率如何,都提供的是约定的同步访问接口。


处理客户端和服务端的数据更新:

客户端的数据有时候随着需求需要每秒钟及时更新数据

普遍的做法都是每秒轮询服务端的数据然后更新客户端

如果这样的话肯定会造成服务器压力过大等问题,因为要频繁地请求和频繁地做数据库查询操作。

那么有没有更好的解决方案,来解决此类问题呢?

android


问题补充:

先说说我现在的做法,我是用的长轮询方式,貌似就是大家说的服务器推吧。我不知道属于不属于服务器推,现在是一个请求过去之后 服务端做一个阻塞,服务端进行一个2分钟的轮询数据库,每一秒select一次直到数据库发生变化时,我返回一个true给客户端,然后客户端更新,这样是可以做到实时更新的。

但我的重点是如果减少每一秒select,因为客户端可能有50-100个左右,都用这种机制,服务器每秒钟做查询,这个靠谱吗?  

现在是客户端安卓平板 + IIS服务器 + SQLSERVER2000

平板使用http协议进行post请求 服务器每秒查询数据库 然后查到更新或超过2分钟返回结果给客户端。

我是觉得服务器好累 怕它扛不住。



客户端轮询是最省力的方式,因为只涉及到查询,不涉及到连接保持,服务器可以通过缓存最新的数据的方式,来隔离数据库查询,客户端的每次查询总会从服务器的缓存中读取最新数据。

服务器推模式有两种,一种是Comet,也就是基于HTTP长连接服务器推技术,就是你在使用的,另一种就是真正的服务器推送模式,但是是基于TCP的。从性能上看,前者会比后者占用更多的服务器资源,后者会在实时性要求较高,而网络又允许的情况下使用。


服务器如何做缓存呢,每秒检测最新的。这要怎么缓存。我也想过缓存起来,不过没想通啊,请launcher指教。


@第五正: 所谓缓存就是把频繁使用的数据放到离你的Web Server最近的地方,通常来说就是宿主你的应用程序的进程的内存中。你可以可以使用第三方的缓存组件来简化缓存项的管理工作。基本的流程应该是这样,客户端每T时间间隔发起一次查询请求,服务器根据客户端请求中携带的上次已更新标记从本地缓存中读取到当前为止的所有匹配数据并返回给客户端,如果服务器本地缓存中没有则从数据库查询,从数据库查询的结果会用来更新本地的缓存。缓存项的过期策略需要根据你的数据的特点来制定,正确总结数据特点,将帮助你制定适当的过期策略。


adb:Android debug bridge(安卓调试桥)

java面试:

如何打印字符串的所有子集:

今天针对这个问题,想了比较多的想法,发现,在处理一个问题的时候,要针对一个处理办法好好想,不要一时就各种乱想,有种条条大路通罗马的感觉,这对于编程很重要,

第一种方法,我针对使用java里面的substring进行处理:

substring(参数)是java中截取字符串的一个方法有两种传参方式一种是public String substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串。该子字符串从指定索引处的字符开始,直到此字符串末尾。另一种是public String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。 详情请参考API  java.lang.String至于LZ说的String subString;subString=number.subString(i,i+1);定义一个String类型的变量去存储number截取第i个位置到第i+1个位置的字符串笼统说就是 我们去截取number的第i个到第i+1个的字符,然后赋值给String类型的变量subString

程序为:

public class Threadtest{
static String str=null;
static String a=null;
static int start=0;
static int len=1;
public static void main(String[] args) throws IOException  {
System.out.println("请输入字符串");
InputStream input=System.in;
InputStreamReader inputread=new InputStreamReader(input);
BufferedReader br=new BufferedReader(inputread);

try {

str=br.readLine();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
br.close();
inputread.close();
input.close();
}

Threadtest tt=new Threadtest(str, start, len);
}
public Threadtest(String string,int start,int len) {
while(start<string.length()){
while(len<=string.length()){
 a=str.substring(start,len);
     System.out.println(a);
     len++;
}
start++;
len=start+1;
     }
}
}

那问题很明显,使用substring,当abc组合中的ac子集是无法实现的,因此还需要改进:

以下是改进的程序:

public class Threadtest{
static char[] Set=new char[]{'q','w','e','r'};
static int[] flag=new int[]{0,0,0,0};
public static void main(String[] args){
Threadtest tt=new Threadtest();
}
public Threadtest(){
int n=2<<3;
for(int m=0;m<n;m++){
this.GetOrNo();
this.PrintSubSet();
}
}
public void GetOrNo(){
for(int i=0;i<4;i++){
flag[i]=flag[i]^1;
if(flag[i]==0) break;
}
}
public void PrintSubSet(){
for(int j=0;j<4;j++){
if(flag[j]==1)
System.out.print(Set[j]);
}
System.out.println();
}
}

摒弃使用循环嵌套的思维,改用面向对象的思维,取或者不取,也就是说对于每一个数,要么取要么不取,然后字符串长度的控制使用一个for循环

来控制就行了。


java中网络编程的netty:

java实现单例模式:

GC导致的内存泄露:

0 0
原创粉丝点击