2022年最新版Android安卓面试题+答案精选(每日20题,持续更新中)【二】

2022年最新版Android安卓面试题+答案精选(每日20题,持续更新中)【二】_第1张图片

前言

写在前面:首先是不一次性放出来的原因:资料来之不易,希望大家好好珍惜,每天花一段时间细细的消化这些题目,其次希望大家在阅读题目的时候最好跟着书或者代码一起阅读、一起敲,做到熟稔于心,信手拈来,这样面试的时候才能展现你最自信的一面。

21、AndroidUI的适配

答案:

字体使用sp,使用dp,多使用match_parent,wrap_content,weight 图片资源,不同图片的的分辨率,放在相应的文件夹下可使用百分比代替。

22、Activity生命周期(这个是必问的)

答案:

onCreate() 创建活动,做一些数据初始化操作 onStart() 由不可见变为可见 onResume() 可以与用户进行交互,位于栈顶 onPause() 暂停,启动或恢复另一个活动时调用 onStop() 停止,变为不可见 onDestroy() 销毁 onRestart() 由停止状态变为运行状态。

23、Android中的动画有哪些

答案:

逐帧动画(Frame Animation) 加载一系列Drawable资源来创建动画,简单来说就是播放一系列的图片来实现动画效果,可以自定义每张图片的持续时间

补间动画(Tween Animation) Tween可以对View对象实现一系列动画效果,比如平移,缩放,旋转,透明度等。但是它并不会改变View属性的值,只是改变了View的绘制的位置,比如,一个按钮在动画过后,不在原来的位置,但是触发点击事件的仍然是原来的坐标。

属性动画(Property Animation) 动画的对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性值被实实在在的改变了。

24、网络框架有哪些?他们之间的区别是什么?

答案:

Xutils 这个框架非常全面,可以进行网络请求,可以进行图片加载处理,可以数据储存,还可以对view进行注解,使用这个框架非常方便,但是缺点也是非常明显的,使用这个项目,会导致项目对这个框架依赖非常的严重,一旦这个框架出现问题,那么对项目来说影响非常大的

OKhttp Android开发中是可以直接使用现成的api进行网络请求的。就是使用HttpClient,HttpUrlConnection进行操作。okhttp针对Java和Android程序,封装的一个高性能的http请求库,支持同步,异步,而且okhttp又封装了线程池,封装了数据转换,封装了参数的使用,错误处理等。API使用起来更加的方便。但是我们在项目中使用的时候仍然需要自己在做一层封装,这样才能使用的更加的顺手。

Volley Volley是Google官方出的一套小而巧的异步请求库,该框架封装的扩展性很强,支持HttpClient、HttpUrlConnection, 甚至支持OkHttp,而且Volley里面也封装了ImageLoader,所以如果你愿意你甚至不需要使用图片加载框架,不过这块功能没有一些专门的图片加载框架强大,对于简单的需求可以使用,稍复杂点的需求还是需要用到专门的图片加载框架。Volley也有缺陷,比如不支持post大数据,所以不适合上传文件。不过Volley设计的初衷本身也就是为频繁的、数据量小的网络请求而生。

Retrofit Retrofit是Square公司出品的默认基于OkHttp封装的一套RESTful网络请求框架,RESTful是目前流行的一套api设计的风格, 并不是标准。Retrofit的封装可以说是很强大,里面涉及到一堆的设计模式,可以通过注解直接配置请求,可以使用不同的http客户端,虽然默认是用http ,可以使用不同Json Converter 来序列化数据,同时提供对RxJava的支持,使用Retrofit + OkHttp + RxJava + Dagger2 可以说是目前比较潮的一套框架,但是需要有比较高的门槛。

Volley VS OkHttp Volley的优势在于封装的更好,而使用OkHttp你需要有足够的能力再进行一次封装。而OkHttp的优势在于性能更高,因为 OkHttp基于NIO和Okio ,所以性能上要比 Volley更快。IO 和 NIO这两个都是Java中的概念,如果我从硬盘读取数据,第一种方式就是程序一直等,数据读完后才能继续操作这种是最简单的也叫阻塞式IO,还有一种是你读你的,程序接着往下执行,等数据处理完你再来通知我,然后再处理回调。而第二种就是 NIO 的方式,非阻塞式, 所以NIO当然要比IO的性能要好了,而 Okio是 Square 公司基于IO和NIO基础上做的一个更简单、高效处理数据流的一个库。理论上如果Volley和OkHttp对比的话,更倾向于使用 Volley,因为Volley内部同样支持使用OkHttp,这点OkHttp的性能优势就没了, 而且 Volley 本身封装的也更易用,扩展性更好些。

OkHttp VS Retrofit 毫无疑问,Retrofit 默认是基于 OkHttp 而做的封装,这点来说没有可比性,肯定首选 Retrofit。

Volley VS Retrofit 这两个库都做了不错的封装,但Retrofit解耦的更彻底,尤其Retrofit2.0出来,Jake对之前1.0设计不合理的地方做了大量重构, 职责更细分,而且Retrofit默认使用OkHttp,性能上也要比Volley占优势,再有如果你的项目如果采用了RxJava ,那更该使用 Retrofit 。所以这两个库相比,Retrofit更有优势,在能掌握两个框架的前提下该优先使用 Retrofit。但是Retrofit门槛要比Volley稍高些,要理解他的原理,各种用法,想彻底搞明白还是需要花些功夫的,如果你对它一知半解,那还是建议在商业项目使用Volley吧。

25、如何实现Fragment的滑动?

答案:

将Fragment与viewpager绑定,通过viewpager中的touch事件,会进行move事件的滑动处理。

Fragment布局



    

    
    
Fragment代码:

public class FragmentOne extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
           return inflater.inflate(R.layout.fragment_one, container, false);
}

}
public class FragmentTwo extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
   return inflater.inflate(R.layout.fragment_Two, container, false);
}
}

viewpager布局:

xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.spreadtrumshitaoli.fragmentscroll.MainActivity">


MainActivity代码:

public class MainActivity extends AppCompatActivity {
private FragmentOne fragmentOne;
private FragmentTwo fragmentTwo;
 
private ViewPager viewPager;
 
private ArrayList mFragmentList = new ArrayList ();
private FragmentPagerAdapter fragmentPagerAdapter;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    init();
 
}
 
private void init() {
 
    viewPager = (ViewPager) findViewById(R.id.view_pager);
    fragmentOne = new FragmentOne();
    fragmentTwo = new FragmentTwo();
 
    mFragmentList.add(fragmentOne);
    mFragmentList.add(fragmentTwo);
    
    //将adapter和fragment绑定在一起。
        fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int i) {
                return mFragmentList != null ? mFragmentList.get(i) : null;
            }
            @Override
        public int getCount() {
            return mFragmentList != null ? mFragmentList.size() : 0;
        }
    };
    viewPager.setAdapter(fragmentPagerAdapter);
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {
 
        }
 
        @Override
        public void onPageSelected(int i) {
            //TODO:
        }
 
        @Override
        public void onPageScrollStateChanged(int i) {
 
        }
    });
 
}
   } 

在这段代码中,我们

首先fragment以及viewpager都实例化;

再将fragment添加到泛型arraylist里;

最后将带有fragment的arraylist和adapter绑定。

26、Android Activity 怎么和Service 绑定?

答案:

这需要实现service中的onBind()函数以返回service实例给activity

1、创建service类和activity类。

2、在service类中定义一个内部类继承自Binder()类:

public class MyBinder extends Binder{  
     public Service1 getService(){  
          return Service1.this;  
     }  
} 

实例化onBind()方法:

private final IBinder binder = new MyyBinder();
@Override
public IBinder onBind(Intent intent){
    Log.i(LOG,"onBind......");
    return binder;
}

3、在activity中完成绑定

Intent intent = new Intent(Activity1.this,Activity2.class);
bindService(intent,conn,Context.BIND_AUTO_CREATE);

bindService的第二个参数是一个ServiceConnection类型的参数。service和其他组件之间的连接都表示为一个ServiceConnection,要想将service和其他组件进行绑定,就需要实现一个新的ServiceConnection。

public ServiceConnection conn= new ServiceConnection() {  
   @Override  
    public void onServiceDisconnected(ComponentName name) {  
    		//当连接意外断开时调用
            Log.i(LOG, "onServiceDisconnected>>>>>>>>");  
            myservice = null;  
    
   } 

   @Override  
    public void onServiceConnected(ComponentName name, IBinder service) {  
    //当建立连接时调用
   Log.i(LOG, "onServiceConnected>>>>>>>>");  
        myservice = ((Service1.MyBinder)service).getService();  
    }  
};

bindService的第三个参数是一个flag。 可以使用的flag有:

BIND_AUTO_CREATE:绑定完成后就启动目标service

BIND_DEBUG_UNBIND:这只在debug时使用,跟unbind有关。

BIND_NOT_FOREGROUND:确保被绑定的service永远不会有运行于前台的优先级,因为默认情况下,绑定一个service会提高它的优先级

BIND_ABOVE_CLIENT:确保客户端处于前台时,绑定的service也变为前台进程

BIND_ALLOW_OOM_MANAGEMENT:允许系统在低内存等状态下删除该service(这是自己对源码中注释的理解)

BIND_WAIVE_PRIORITY:绑定service时不改变其优先级

BIND_ADJUST_WITH_ACTIVITY:系统根据service所绑定的activity的重要程度来调整这个service的优先级。

27、onNewIntent()调用时机?

答案:

singleTop:如果新Activity已经位于任务栈的栈顶,就不会重新创建,并回调 onNewIntent(intent) 方法。 singleTask:只要该Activity在一个任务栈中存在,都不会重新创建,并回调 onNewIntent(intent) 方法。

28、Android与服务器交互的方式中的对称加密和非对称加密是什么?

答案:

对称加密,就是加密和解密数据都是使用同一个key,这方面的算法有DES。 非对称加密,加密和解密是使用不同的key。发送数据之前要先和服务端约定生成公钥和私钥,使用公钥加密的数据可以用私钥解密,反之。这方面的算法有RSA。ssh 和 ssl都是典型的非对称加密。

29、android 启动模式:

答案:

1、standard:标准化启动模式

每启动一个Activity,都会重新创建Activity的新的实例,将其放在栈的顶部。不需要考虑这个实例是否已经存在。

每一次启动,它的onCreate()、onStart()、onResume()方法都会被依次调用。

2、singleTop:栈顶复用模式

当前栈中已经有该Activity实例,并且该实例位于栈顶时,会去调用onNewIntent()方法。

当前栈中已有该Activity的实例但是该实例不在栈顶时,依然会去创建Activity。

当前栈中不存在该Activity实例时,会去新创建一个该Activity。

应用场景:IM对话框、新闻客户端推送。

3、singleTask:栈内复用模式

它主要检测【寻找,通过taskAffinity】整个栈中是否已经存在当前想要启动的Activity,存在的话直接将该Activity置于栈顶,之前位于该Activity上面的Activity将被销毁,同时调用onNewIntent()方法,而不存在的话进行创建。

应用场景:应用主界面。

4、singleInstance:

一个人独享一个任务栈。当该Activity启动时,系统会创建一个新的任务栈,同时将Activity放到这个新的任务栈当中,有别的应用来启动该Activity时,由于栈内复用的特性,不会再去创建相应Activity任务栈,而是这两个应用独享一个Activity实例。

例如:应用A中现有两个Activity E、Activity F,为standard启动模式,应用B中有一个Activity G,但其启动模式是singleInstance。应用A想用应用B任务栈当中的Activity G,尽管在不同的应用下,但是应用A仍然会直接复用Activity G。

特性:

1、以SingleInstance模式启动的Activity具有全局唯一性【全局唯一性即指在整个系统当中只会存在一个这样的实例】;

2、如果在启动这样一个Activity时,【整个系统都是单例的】,已经存在了一个实例;

3、以SingleInstance模式启动的Activity具有独占性。

应用场景:呼叫来电。

30、谈谈ContentProvider、ContentResolver、ContentObserver之间的关系?

答案:

ContentProvider:

  • 四大组件的内容提供者,主要用于对外提供数据
  • 实现各个应用程序之间的(跨应用)数据共享,比如联系人应用中就使用了ContentProvider,你在自己的应用中可以读取和修改联系人的数据,不过需要获得相应的权限。其实它也只是一个中间人,真正的数据源是文件或者SQLite等
  • 一个应用实现ContentProvider来提供内容给别的应用来操作,通过ContentResolver来操作别的应用数据,当然在自己的应用中也可以

ContentResolver:

  • 内容解析者,用于获取内容提供者提供的数据
  • ContentResolver.notifyChange(uri)发出消息

ContentObserver:

  • 内容监听器,可以监听数据的改变状态
  • 目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObsever也分为表ContentObserver、行ContentObserver,当然这是与它所监听的Uri MIME Type有关的
  • ContentResolver.registerContentObserver()监听消息。

31、如何优化ListView(偶尔会问)

答案:

①Item布局,层级越少越好,使用hierarchyview工具查看优化。
②复用convertView
③使用ViewHolder
④item中有图片时,异步加载
⑤快速滑动时,不加载图片
⑥item中有图片时,应对图片进行适当压缩
⑦实现数据的分页加载

32、Android service生命周期?

答案:

  1. 被启动的服务(startService())的生命周期。 如果一个Service被某个Activity 调用Context.startService() 方法启动,那么不管是否有Activity使用bindService()绑定或unbindService()解除绑定到该Service,该Service都在后台运行。如果一个Service被多次执行startService(),它的onCreate()方法只会调用一次,也就是说该Service只会创建一个实例,而它的onStartCommand()将会被调用多次(对应调用startService()的次数)。该Service将会一直在后台运行,直到被调用stopService(),或自身的stopSelf方法。当然如果系统资源不足,系统也可能结束服务。
  2. 被绑定的服务(bindService())的生命周期。 如果一个Service被调用 Context.bindService ()方法绑定启动,不管调用bindService()调用几次,onCreate()方法都只会调用一次,而onStartCommand()方法始终不会被调用,这时会调用onBind()方法。当连接建立之后,Service将会一直运行,除非调用Context.unbindService() 断开连接或者之前调用bindService() 的 Context 不存在了(如该Activity被finish),系统将会自动停止Service,对应onDestroy()将被调用。
  3. 被启动又被绑定的服务的生命周期。 如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。调用unbindService()将不会停止Service,而必须调用stopService()或Service的stopSelf()方法来停止服务。
  4. 当服务被停止时清除服务。 当一个Service被终止时,Service的onDestroy()方法将会被调用,在这里应当做一些清除工作,如停止在Service中创建并运行的线程等。

33、设备横竖屏切换的时候,生面周期的变化(这个偶尔会问)

答案:

不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。

34、Android Service的启动方式?

答案:

采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的 onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方 法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致 多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用 unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()–>onDestroy()方法。

35、activity和service的绑定方式以及怎么在Activity 中启动自己对应的Service?

答案:

1、activity能进行绑定得益于Serviece的接口。为了支持Service的绑定,实现onBind方法。

2、Service和Activity的连接可以用ServiceConnection来实现。需要实现一个新的ServiceConnection,重现onServiceConnected和OnServiceDisconnected方法,一旦连接建立,就能得到Service实例的引用。

3、执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显示或隐式)和一个你实现了的ServiceConnection的实例。

36、Android Service生命周期?

答案:

onCreate() 首次创建服务时,系统将调用此方法。如果服务已在运行,则不会调用此方法,该方法只调用一次。

onStartCommand() 当另一个组件通过调用startService()请求启动服务时,系统将调用此方法。

onDestroy() 当服务不再使用且将被销毁时,系统将调用此方法。

onBind() 当另一个组件通过调用bindService()与服务绑定时,系统将调用此方法。

onUnbind() 当另一个组件通过调用unbindService()与服务解绑时,系统将调用此方法。

onRebind() 当旧的组件与服务解绑后,另一个新的组件与服务绑定,onUnbind()返回true时,系统将调用此方法。

37、Android Service启动方式

答案:

1.startService

①.定义一个类继承service

②.在manifest.xml文件中配置该service

③.使用context的startService(intent)启动该service

④.不再使用时,调用stopService(Intent)停止该服务

2.bindService

①.创建bindService服务段,继承自service并在类中,创建一个实现binder接口的实例对象并提供公共方法给客户端调用

②.从onbind()回调方法返回此binder实例

③.在客户端中,从onserviceconnected()回调方法接收binder,并使用提供的方法调用绑定服务

5.Activity的启动方式(偶尔会问)

①.standard模式

a.Activity的默认启动模式
b.每启动一个Activity就会在栈顶创建一个新的实例。例如:闹钟程序
缺点:当Activity已经位于栈顶时,而再次启动Activity时还需要在创建一个新的实例,不能直接复用。

②.singleTop模式

特点:该模式会判断要启动的Activity实例是否位于栈顶,如果位于栈顶直接复用,否则创建新的实例。 例如:浏览器的书签。
缺点:如果Activity并未处于栈顶位置,则可能还会创建多个实例。

③.singleTask模式

特点:使Activity在整个应用程序中只有一个实例。每次启动Activity时系统首先检查栈中是否存在当前Activity实例,如果存在
则直接复用,并把当前Activity之上所有实例全部出栈。例如:浏览器主界面

④.singleInstance模式

特点:该模式的Activity会启动一个新的任务栈来管理Activity实例,并且该势力在整个系统中只有一个。无论从那个任务栈中启动该Activity,都会是该Activity所在的任务栈转移到前台,从而使Activity显示。主要作用是为了在不同程序中共享一个Activity

38、单选题线程是Android中经常用到的场景,一般都是继承Runnable然后实现run方法,当开启线程时,调用以下哪个方法,就会自动执行run方法?
A. doRun()

B. start();

C. doAction();

D. doStart();

答案: B。

39、关于Android手势分发顺序下列正确的是:

A. dispatchTouchEvent→onInterceptTouchEvent→onTouchEvent

B. dispatchTouchEvent→onTouchEvent→onInterceptTouchEvent

C. onInterceptTouchEvent→dispatchTouchEvent→onTouchEvent

D. onTouchEvent→onInterceptTouchEvent→dispatchTouchEvent

答案:A。

40.下面那个方法可以比较两个NSString *str1, *str2 的异同

A. if(str1 = str2) xxx ;

B. if([str1 isEqualToString:str2]) xxx ;

C. if(str1 && str2) xxx ;

D. if([str1 length] == [str2 length]) xxx;

答案:B;这是一个实现跑马灯效果通过自定义类,派生于TextView,并实现Runnable接口的效果。请在代码区实现获得textview文字的宽度,以及run方法。

结尾

今天的二十题安卓面试题就到此为止了,关注我,后续每日都会准时更新哦,喜欢的朋友不要吝啬你的赞和收藏哦,那我们明天再见!

你可能感兴趣的:(面试,android,经验分享,android-studio,android,studio)