Android面试题(二)

247 阅读8分钟

31、描述一下广播接收者的生命周期** **

无论是动态注册广播接收者还是静态注册广播接收者,指的都是将广播接收者注册到系统中,注意,只是注册到系统中而已,并没有实例化,真正实例化是在接受到广播的时候,系统将广播接收者实例化,然后执行onReceive方法,当onReceive方法执行结束之后,生命周期就结束了 。所以在onReceive方法中启动的线程,很容易被系统回收,如果在onReceive中有耗时的操作,那么可以使用service

32、如** BroadcastReceiver 广 广 **

isOrderedBroadcast()

33服务的启动方式有哪些?** **

startService和bindService

a、通过startService

Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调          用onDestroy方法。

这种方式,activity和service是相互独立的。如果是调用者自己直接退出而没                     有调用stopService的话,Service会一直在后台运行

b、通过bindService

Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑                      定在一起。调用者退出了,Service就会调用onUnbind->onDestroyed方法。

这种方式,activity就和service相互捆绑在一起了。所谓绑定在一起就共存亡                     了。调用者也可以通过调用unbindService方法来停止服务,这时候Service就                           会调用onUnbind->onDestroyed方法。

普通的线程也可以达到在后台做事情的功能,那么为什么使用Service呢?

是因为Service是系统的组件,它的优先级比普通的线程要高,不容易被系统回收。而且线程不好控制,Service相对好控制一些。运行在前台的Activity是不会被系统回收的,而Service如果不想被系统回收,就需要在Service中设置一下

startForeground(int,Notification)

具体的使用场景有:

a、拥有长连接QQ

b、定时轮询

c、服务里面注册广播接收者。有些广播接收者只能通过代码注册,比如屏幕锁屏、屏幕解锁

34、聊一聊Android****中跨进程访问方式 **

Android中跨进程访问的方式:**主要广播 、AIDL 、Intent

intent:

与电话应用通讯

Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse("tel:"+number));

  1. startActivity(intent);

与短信应用通讯

Uri uri = Uri.parse("smsto:" + number);

Intent sendIntent = new Intent(Intent.ACTION_VIEW, uri);

sendIntent.putExtra("sms_body", message);

  1. startActivity(sendIntent);

与浏览器应用通讯

Intent intent = new Intent();

intent.setAction("android.intent.action.VIEW");

Uri content_url = Uri.parse("http://www.cnblogs.com");

intent.setData(content_url);

startActivity(intent);

AIDL的全称是android interface definition language  接口定义语言。它所做的事情就是跨进程调用另外一个服务里面的方法的。在手机卫士中挂断电话用到过         AIDL。我们要获取手机系统的电话服务,用到了aidl 它其实工作的原理就是绑定到一个远程的服务上。然后这个远程服务会返回回来一个代理对象。这个代理对象里面的方法,就是我们定义的aidl里面的方法。

aidl的写法也非常简单,主要分两种。调用系统服务的话,直接找到那个服务的aidl拷贝到我们的项目中就可以了。另外一种是我们自己写aidl,主要注意的一      点是aidl是没有访问修饰符的。因为aidl本身就是公开的,就是为了给别人调用         的,不需要私有的private方法。

其实,在实际的开发过程中,比较少会写这个aidl,但是你得懂它相关的知识点。

有几个关键点 1、跨进程  2、aidl在服务端和客户端都需要有一份  3、通过绑定bindService的方式获取远程服务对象的代理IBinder,就可以调用相关的方法。

**跨进程的底层原理 **

广播、aidl 的底层实现机制是Binder,Binder是基于共享内存的一种IPC方式

如何自己实现进程间的通信?

35Android工程目录结构** **

src

res

assets

libs

AndroidManifest

37、谈谈** UI 中, Padding Margin **有什么区别? **

android:padding 和 android:layout_margin 的区别,其实概念很简单,padding 是站在父view 的角度描述问题,它规定它里面的内容必须与这个父view 边界的距离。margin 则是站在自己的角度描述问题,规定自己和其他(上下左右)的view 之间的距离

对于内边距而言,还可以通过.9的图片进行处理

38、**android:layout_gravity android:gravity 的区别? **

第一个是让该布局在其父控件中的布局方式,第二个是该布局布置其子控件的布局方式。

39、**ListView 如何提高其效率? **

ListView可以显示非常多的条目信息,每一个条目就是一个View对象,如果为每一个条目都新建一个View对象的话,那么会非常影响内存以及流畅度,这时候可以使用系统提供的缓存convertView进行优化。具体优化的方法如下:

1、使用convertView,减少inflate布局文件的次数

2、使用ViewHolder,减少findViewById的次数

3、使用分页加载机制

40ListView内容错位,图片错位** **

正是由于使用的缓存convertView,才造成了内容的错位,图片的错位,此时应该仔细检查getView中的代码,看下是不是在某些特定的条件下没有刷新View

getView的工作包括以下四个部分:

1.加载布局

2.初始化控件

3.设置tag

4.刷新数据

防止ListView图片错位,需要在第4个步骤,也就是刷新数据的时候,将所有的情况都考虑进去,不要使得处于某一些position的view没有进行刷新数据的操作。

41ListView的分页加载** **

有两种方式:

方式一:监听ListView的滚动状态,在状态为静止的时候,判断最后一条可见条目是否就是数据集合中的最后一条。

① 设置 ListView 的滚动监听器:setOnScrollListener(new OnScrollListener{….}) 在监听器中有两个方法: 滚动状态发生变化的方法(onScrollStateChanged)和 listView 被滚动时调用的方法(onScroll) ② 在滚动状态发生改变的方法中,有三种状态: 手指按下移动的状态: SCROLL_STATE_TOUCH_SCROLL: // 触摸滑动 惯性滚动(滑翔(flging)状态): SCROLL_STATE_FLING: // 滑翔 静止状态: SCROLL_STATE_IDLE: // 静止 对不同的状态进行处理: 分批加载数据,只关心静止状态:关心最后一个可见的条目,如果最后一个可见条目就是数据适配器(集合)里 的最后一个,此时可加载更多的数据。在每次加载的时候,计算出滚动的数量,当滚动的数量大于等于总数量的时候,

方式二:在getView中判断position的值是否为最后一条即可。

** **

42ListView显示多种布局类型** **

1.重写getViewTypeCount:返回ListView要显示View的类型的个数,此时写2

2..重写getItemViewType(int position):根据position的位置来确定要返回哪种布局类型

3.在getView中根据getItemViewType(int position)的返回值来加载不同的view布局

43、什么时候使用ListView、什么时候使用**LinearLayout **

当显示条目如果是少量、确定的时候,可以使用LinearLayout,根据情况可以在外层套一个ScrollView,因为LinearLayout比较简单,不需要使用adapter

如果显示的条目很多,或者数量不确定的情况下,那么使用ListView会更合理一些。

45、如何使用**ViewPager **

一般在进行View的左右滑动切换的时候,我们会使用到ViewPager,比如广告轮播条,比如一些页签布局,在使用ViewPager的时候需要设置一个Adapter,当ViewPager显示基本的View,则需要用PagerAdapter,当ViewPager显示Fragment,则需要使用FragmentPagerAdapter

在使用ViewPager的时候,我们通常会加上一个指示器indicator,这时候需要监听ViewPager的onPageChangedListener

指示器:可以自己实现也可以使用第三方框架,如ViewPagerIndicator,PagerTab等

46、如何防止ViewPager预加载** **

默认的情况下,ViewPager至少会预加载下一页的界面。可以通过viewPager.setOffscreenPageLimit(5);来修改预加载的数量,不过不能设置为0,因为通过查看代码发现,如果设置的值小于1的话,那么将不生效

public void setOffscreenPageLimit(int limit) {

if (limit < DEFAULT_OFFSCREEN_PAGES) {

Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +

DEFAULT_OFFSCREEN_PAGES);

limit = DEFAULT_OFFSCREEN_PAGES;

}

if (limit != mOffscreenPageLimit) {

mOffscreenPageLimit = limit;

populate();

}

}

DEFAULT_OFFSCREEN_PAGES的值为1,如果要完全禁止ViewPager的预加载,只有通过自己实现一个ViewPager才能达到。或者使用一个开源控件LazyViewPager

_sta�w5��