Android面试题【初级工程师版】

转自:https://blog.csdn.net/fishmai/article/details/51981827

初级工程师面试题

 

Android 基础(2016.01.20 更新)(★★).
一、 Activity
1、 什么是 Activity?
2、 请描述一下 Activity 生命周期
3、 常见的 Activity 类型
4、 如何保存 Activity 的状态?
5、 两个 Activity 之间跳转时必然会执行的是哪几个方法?
6、 横竖屏切换时 Activity 的生命周期
7、 如何将一个 Activity 设置成窗口的样式
8、 如何退出 Activity?如何安全退出已调用多个 Activity 的Application?
9、 Activity 的四种启动模式
10、 Android 中的 Context, Activity,Appliction 有什么区别?
11、 两个 Activity 之间传递数据,除了 intent,广播接收者,content provider 还有啥?

12、 Context是什么?
13、 如果后台的 Activity 由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
14、你后台的 Activity 被系统回收怎么办?【较难】
15、怎么在启动一个 Activity 时就启动一个 service?
16、同一个程序,但不同的 Activity 是否可以放在不同的 Task 任务栈中?
17  Activity 怎么和 service 绑定,怎么在 activity 中启动自己对应的 service? 

 


二、 Service
1、 Service 是否在 main thread 中执行, service 里面是否能执行耗时的操作?
2、 Activity 怎么和Service 绑定,怎么在 Activity 中启动自己对应的 Service?
3、 请描述一下 Service 的生命周期
4、 什么是 IntentService?有何优点?
5、 说说 Activity、Intent、Service 是什么关系
6、 Service 和 Activity 在同一个线程吗
7、 Service 里面可以弹吐司么
8、 什么是 Service 以及描述下它的生命周期。Service 有哪些启动方法,有什么区别,怎样停用 Service?

9、 在 service 的生命周期方法 onstartConmand()可不可以执行网络操作?如何在 service 中执行网络操作?
10 不用 service,B 页面为音乐播放,从 A 跳转到 B,再返回,如何使音乐继续播放? 
11  什么时候使用 Service?

 


三、 Broadcast Receiver
1、 请描述一下 BroadcastReceiver
2、 在 manifest 和代码中如何注册和使用 BroadcastReceiver
3、 BroadCastReceiver的生命周期
四、 ContentProvider
1、 请介绍下 ContentProvider 是如何实现数据共享的
2、 请介绍下 Android 的数据存储方式
3、 为什么要用 ContentProvider?它和sql 的实现上有什么差别?
4、 说说 ContentProvider、ContentResolver、ContentObserver 之间的关系


五、 ListView
1、 ListView 如何提高其效率?
2、 当 ListView 数据集改变后,如何更新 ListView.
3、 ListView 如何实现分页加载
4、 ListView 可以显示多种类型的条目吗
5、 ListView 如何定位到指定位置
6、 如何在 ScrollView 中如何嵌入 ListView
7、 ListView 中如何优化图片
8、 ListView 中图片错位的问题是如何产生的
9、 如何刷新 ListView 中单个 item 的数据,不刷新整个ListView 的数据?


六、 Intent
1、 Intent 传递数据时,可以传递哪些类型数据?
2、 Serializable 和 Parcelable 的区别
3、 请描述一下 Intent 和 IntentFilter
七、 Fragment
1、 Fragment 跟 Activity 之间是如何传值的
2、 描述一下 Fragment 的生命周期
3、 Fragment 的 replace 和 add 方法的区别
4、 Fragment 如何实现类似 Activity 栈的压栈和出栈效果的?
5、 Fragment 在你们项目中的使用
6、 如何切换 fragement,不重新实例化
 

 

一、 Activity
1、什么是Activity?
四大组件之一,一般的,一个用户交互界面对应一个 activity
setContentView() ,// 要显示的布局
button.setOnclickLinstener{
}, activity 是Context的子类,同时实现了window.callback和keyevent.callback, 可以处理与窗体
用户交互的事件.
我开发常用的的有FragmentActivitiyListActivity ,PreferenceActivity ,TabAcitivty 等…


2、请描述一下 Activity 生命周期
Activity 从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回
调方法包括:onCreate onStart onResume onPause onStop onDestroy
其实这些方法都是两两对应的,onCreate创建与 onDestroy 销毁;
onStart 可见与onStop 不可见;onResume可编辑(即焦点)与onPause;
如果界面有共同的特点或者功能的时候,还会自己定义一个 BaseActivity.
进度对话框的显示与销毁


3、常 见 的 Activity 类 型 有 FragmentActivitiy , ListActivity ,
TabAcitivty 等。请描述一下Activity 生命周期
Activity 从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:onCreate onStart onResume onPause onStop onDestroy
其实这些方法都是两两对应的,onCreate创建与 onDestroy 销毁;
onStart 可见与onStop 不可见;onResume可编辑(即焦点)与onPause。


4、如何保存Activity 的状态?
Activity 的状态通常情况下系统会自动保存的,只有当我们需要保存额外的数据时才需要使用到这样的功能。
一般来说, 调用onPause()和onStop()方法后的activity实例仍然存在于内存中, activity的所有信息和状态数据不会消失, 当activity 重新回到前台之后, 所有的改变都会得到保留。
但是当系统内存不足时, 调用 onPause()和 onStop()方法后的 activity 可能会被系统摧毁, 此时内存中就不会存有该 activity 的实例对象了。如果之后这个 activity 重新回到前台, 之前所作的改变就 会 消 失 。 为 了 避 免 此 种 情 况 的 发 生 , 我 们 可 以 覆 写 onSaveInstanceState() 方 法 。
onSaveInstanceState()方法接受一个 Bundle 类型的参数, 开发者可以将状态数据存储到这个Bundle对象中, 这样即使activity被系统摧毁, 当用户重新启动这个activity而调用它的onCreate()方法时, 上述的 Bundle 对象会作为实参传递给 onCreate()方法, 开发者可以从 Bundle 对象中取出保存的数据, 然后利用这些数据将activity 恢复到被摧毁之前的状态。
需要注意的是, onSaveInstanceState()方法并不是一定会被调用的, 因为有些场景是不需要保存状态数据的. 比如用户按下BACK键退出activity时, 用户显然想要关闭这个activity, 此时是没有必要保存数据以供下次恢复的, 也就是 onSaveInstanceState()方法不会被调用. 如果调用onSaveInstanceState()方法, 调用将发生在 onPause()或 onStop()方法之前。
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
}


5、两个 Activity 之间跳转时必然会执行的是哪几个方法?
一般情况下比如说有两个activity,分别叫A,B,当在A里面激活B组件的时候, A会调用 onPause()
方法,然后 B 调用 onCreate() ,onStart(), onResume()。
这个时候B 覆盖了窗体, A 会调用 onStop()方法. 如果 B 是个透明的,或者是对话框的样式, 就
不会调用A的 onStop()方法。


6、横竖屏切换时Activity 的生命周期
此时的生命周期跟清单文件里的配置有关系。
1.不设置Activity 的 android:configChanges时, 切屏会重新调用各个生命周期默认首先销毁
当前 activity,然后重新加载。
2.设置 Activity android:configChanges="orientation|keyboardHidden|screenSize"时,切
屏不会重新调用各个生命周期,只会执行onConfigurationChanged 方法。
通常在游戏开发, 屏幕的朝向都是写死的。


7、如何将一个 Activity 设置成窗口的样式
只需要给我们的Activity 配置如下属性即可。
android:theme="@android:style/Theme.Dialog"


8、如 何退 出 Activity ? 如何 安全 退出 已 调用 多个 Activity 的Application?
1、通常情况用户退出一个 Activity 只需按返回键,我们写代码想退出activity 直接调用 finish()方法就行。
2、记录打开的 Activity:
每打开一个 Activity,就记录下来。在需要退出时,关闭每一个Activity 即可。
//伪代码
List<Activity> lists ;// 在 application 全局的变量里面
lists = new ArrayList<Activity>();
lists.add(this);
for(Activity activity: lists)
{
activity.finish();
}
lists.remove(this);
3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity 收到广播后,关闭即可。
//给某个 activity 注册接受接受广播的意图
registerReceiver(receiver, filter)
//如果过接受到的是 关闭 activity 的广播 就调用 finish()方法 把当前的 activity finish()掉
4、递归退出
在打开新的 Activity 时使用 startActivityForResult,然后自己加标志,在 onActivityResult 中
处理,递归关闭。
5、其实 也可以通过 intent的 flag 来实现 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
激活一个新的activity。此时如果该任务栈中已经有该Activity,那么系统会把这个Activity 上面的所有 Activity 干掉。其实相当于给Activity 配置的启动模式为 SingleTop。


9、Activity 的四种启动模式,singletop 和 singletask 区别是什么?
一般书签的使用模式是 singletop,那为什么不使用 singletask?
singleTop 跟 standard 模式比较类似。唯一的区别就是,当跳转的对象是位于栈顶的activity(应
该可以理解为用户眼前所 看到的 activity)时,程序将不会生成一个新的activity 实例,而是直接跳
到现存于栈顶的那个activity 实例。拿上面的例子来说,当 Act1 为 singleTop 模式时,执行跳转
后栈里面依旧只有一个实例,如果现在按返回键程序将直接退出。
singleTask模式和 singleInstance 模式都是只创建一个实例的。在这种模式下,无论跳转的对
象是不是位于栈顶的activity,程序都不会生成一个新的实例(当然前提是栈里面已经有这个实例)。
这种模式相当有用,在以后的多activity 开发中,常会因为跳转的关系导致同个页面生成多个实例,
这个在用户体验上始终有点不好,而如果你将对应的activity 声明为 singleTask 模式,这种问题将
不复存在。在主页的Activity 很常用


10、Android 中的 Context, Activity,Appliction 有什么区别?
相同:Activity 和Application都是 Context的子类。
Context从字面上理解就是上下文的意思, 在实际应用中它也确实是起到了管理上下文环境中各个参
数和变量的总用,方便我们可以简单的访问到各种资源。
不同:维护的生命周期不同。 Context维护的是当前的 Activity 的生命周期,Application维护
的是整个项目的生命周期。
使用 context的时候,小心内存泄露,防止内存泄露,注意一下几个方面:
1. 不要让生命周期长的对象引用activity context,即保证引用 activity 的对象要与 activity 本身
生命周期是一样的。
2. 对于生命周期长的对象,可以使用application,context。
3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致
的生命周期变化。


11、两个Activity 之间传递数据,除了intent,广播接收者,content provider 还有啥?
1)利用 static静态数据,public static成员变量
2)利用外部存储的传输,
例如 File 文件存储
SharedPreferences首选项
Sqlite 数据库


12、Context 是什么?
1、它描述的是一个应用程序环境的信息,即上下文。
2、该类是一个抽象(abstract class)类,Android 提供了该抽象类的具体实现类(ContextIml)。
3、 通过它我们可以获取应用程序的资源和类, 也包括一些应用级别操作, 例如: 启动一个 Activity,
发送广播,接受Intent,信息,等。


二、 Service
1、Service 是否在 main thread 中执行, service 里面是否能执行耗时的操
作?
默认情况,如果没有显示的指 servic所运行的进程, Service 和 activity 是运行在当前 app 所在进
程的 main thread(UI主线程)里面。
service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )
特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另外的进程中执行
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
</service>


2、Activity 怎么和 Service 绑定,怎么在 Activity 中启动自己对应的Service?
Activity 通过 bindService(Intent service, ServiceConnection conn, int flags)跟 Service进行
绑定,当绑定成功的时候 Service 会将代理对象通过回调的形式传给 conn,这样我们就拿到了
Service 提供的服务代理对象。
在Activity 中可以通过 startService 和 bindService 方法启动 Service。一般情况下如果想获取
Service 的服务对象那么肯定需要通过 bindService()方法,比如音乐播放器,第三方支付等。如
果仅仅只是为了开启一个后台任务那么可以使用startService()方法。


3、请描述一下 Service 的生命周期
Service 有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不同的使用方法生命周期
方法也不同。
非 绑 定 模 式 : 当 第 一 次 调 用 startService 的 时 候 执 行 的 方 法 依 次 为 onCreate() 、
onStartCommand(),当 Service 关闭的时候调用onDestory 方法。
绑定模式:第一次 bindService()的时候,执行的方法为 onCreate()、onBind()解除绑定的
时候会执行 onUnbind()、onDestory()。
上面的两种生命周期是在相对单纯的模式下的情形。我们在开发的过程中还必须注意Service 实
例只会有一个,也就是说如果当前要启动的Service 已经存在了那么就不会再次创建该 Service 当然
也不会调用 onCreate()方法。
一个 Service 可以被多个客户进行绑定,只有所有的绑定对象都执行了 onBind()方法后该
Service 才会销毁,不过如果有一个客户执行了 onStart()方法,那么这个时候如果所有的 bind 客户
都执行了unBind()该 Service 也不会销毁。
Service 的生命周期图如下所示,帮助大家记忆。


4、什么是 IntentService?有何优点?
我们通常只会使用 Service,可能 IntentService 对大部分同学来说都是第一次听说。那么看了
下面的介绍相信你就不再陌生了。 如果你还是不了解那么在面试的时候你就坦诚说没用过或者不了解
等。并不是所有的问题都需要回答上来的。
一、IntentService 简介
IntentService 是 Service 的子类,比普通的 Service 增加了额外的功能。先看 Service 本身存在
两个问题:
Service 不会专门启动一条单独的进程,Service 与它所在应用位于同一个进程中;传智播客武汉校区就业部出品 务实、创新、质量、分享、专注、责任
18
Service 也不是专门一条新线程,因此不应该在 Service 中直接处理耗时的任务;
二、IntentService 特征
会创建独立的worker线程来处理所有的Intent请求;
会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
所有请求处理完成后,IntentService 会自动停止,无需调用stopSelf()方法停止 Service;
为Service 的onBind()提供默认实现,返回null;
为Service 的onStartCommand提供默认实现,将请求 Intent添加到队列中;
使用IntentService
本人写了一个 IntentService 的使用例子供参考。该例子中一个 MainActivity 一个
MyIntentService,这两个类都是四大组件当然需要在清单文件中注册。这里只给出核心代码:


MainActivity.java:
public void click(View view){
Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra("start", "MyIntentService");
startService(intent);
}


MyIntentService.java
public class MyIntentService extends IntentService {
private String ex = "";
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
Toast.makeText(MyIntentService.this, "-e " + ex,
Toast.LENGTH_LONG).show();
}
};
public MyIntentService(){
super("MyIntentService");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
ex = intent.getStringExtra("start");
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
/**
* 模拟执行耗时任务
* 该方法是在子线程中执行的,因此需要用到handler 跟主线程进行通信
*/
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.sendEmptyMessage(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行后效果如下:


5、说说 Activity、Intent、Service 是什么关系
他们都是 Android 开发中使用频率最高的类。其中 Activity 和 Service 都是 Android 四大组件
之一。他俩都是 Context类的子类 ContextWrapper的子类,因此他俩可以算是兄弟关系吧。不过
兄弟俩各有各自的本领, Activity 负责用户界面的显示和交互, Service 负责后台任务的处理。 Activity
和 Service 之间可以通过Intent传递数据,因此可以把Intent看作是通信使者。


6、Service 和Activity 在同一个线程吗
对于同一app 来说默认情况下是在同一个线程中的,main Thread (UI Thread)。


7、Service 里面可以弹吐司么
可以的。弹吐司有个条件就是得有一个 Context 上下文,而 Service 本身就是 Context 的子类,因此在 Service 里面弹吐司是完全可以的。比如我们在 Service 中完成下载任务后可以弹一个吐司通知用户。


8、什么是 Service 以及描述下它的生命周期。Service 有哪些启动方法,有什么区别,怎样停用Service?
在 Service 的生命周期中,被回调的方法比Activity 少一些,只有 onCreate, onStart, onDestroy,
onBind和 onUnbind。
通常有两种方式启动一个Service,他们对 Service 生命周期的影响是不一样的。
1. 通过startService
Service会经历 onCreate 到onStart, 然后处于运行状态, stopService的时候调用onDestroy
方法。
如果是调用者自己直接退出而没有调用stopService 的话,Service 会一直在后台运行。
2. 通过bindService
Service 会运行onCreate,然后是调用onBind, 这个时候调用者和 Service 绑定在一起。调
用者退出了,Srevice就会调用 onUnbind->onDestroyed方法。
所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService 方法来停止服务,这时候
Srevice就会调用onUnbind->onDestroyed方法。
需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢?
一个原则是 Service 的 onCreate的方法只会被调用一次,就是你无论多少次的startService 又
bindService,Service 只被创建一次。
如果先是bind了, 那么 start 的时候就直接运行Service 的 onStart 方法, 如果先是 start, 那么 bind
的时候就直接运行onBind方法。
如果 service 运行期间调用了bindService,这时候再调用 stopService 的话,service 是不会调用
onDestroy 方法的,service 就 stop不掉了,只能调用 UnbindService, service 就会被销毁
如果一个service 通过 startService 被 start 之后,多次调用startService 的话,service 会多次调
用 onStart 方法。多次调用stopService 的话,service 只会调用一次 onDestroyed方法。
如果一个service 通过 bindService 被 start 之后,多次调用 bindService 的话,service 只会调用
一次 onBind方法。多次调用unbindService 的话会抛出异常。


9、在 service 的生命周期方法 onstartConmand()可不可以执行网络操作?如何在 service 中执行网络操作?
可以直接在 Service 中执行网络操作,在 onStartCommand()方法中可以执行网络操作


三、 Broadcast Receiver
1、请描述一下 BroadcastReceiver
BroadCastReceiver是 Android四大组件之一,主要用于接收系统或者app 发送的广播事件。
广播分两种:有序广播和无序广播。
内部通信实现机制:通过Android 系统的 Binder机制实现通信。
无序广播:完全异步,逻辑上可以被任何广播接收者接收到。优点是效率较高。缺点是一个接收者不
能将处理结果传递给下一个接收者,并无法终止广播intent的传播。
有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广播接收者 A,B,C,
优先级是A > B > C。那这个消息先传给 A,再传给 B,最后传给 C。每个接收者有权终止广播,比
如 B终止广播,C就无法接收到。此外 A接收到广播后可以对结果对象进行操作,当广播传给 B 时,
B可以从结果对象中取得 A 存入的数据。
在通过 Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
initialCode, initialData, initialExtras)时我们可以指定 resultReceiver广播接收者,这个接收者我们
可以认为是最终接收者,通常情况下如果比他优先级更高的接收者如果没有终止广播,那么他的
onReceive会被执行两次,第一次是正常的按照优先级顺序执行,第二次是作为最终接收者接收。
如果比他优先级高的接收者终止了广播,那么他依然能接收到广播。
在我们的项目中经常使用广播接收者接收系统通知,比如开机启动、sd 挂载、低电量、外播电话、
锁屏等。
如果我们做的是播放器,那么监听到用户锁屏后我们应该将我们的播放之暂停等。


2、在 manifest和代码中如何注册和使用 BroadcastReceiver
在清单文件中注册广播接收者称为静态注册,在代码中注册称为动态注册。静态注册的广播接收者只要 app 在系统中运行则一直可以接收到广播消息,动态注册的广播接收者当注册的 Activity 或
者 Service 销毁了那么就接收不到广播了。
静态注册:在清单文件中进行如下配置
<receiver android:name=".BroadcastReceiver1" >
<intent-filter>
<action android:name="android.intent.action.CALL" >
</action>
</intent-filter>
</receiver>
动态注册:在代码中进行如下注册
receiver = new BroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CALL_ACTION);
context.registerReceiver(receiver, intentFilter);


3、BroadCastReceiver 的生命周期
a. 广播接收者的生命周期非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销
毁;
b. 广播接收者中不要做一些耗时的工作,否则会弹出Application No Response 错误对话框;
c. 最好也不要在广播接收者中创建子线程做耗时的工作, 因为广播接收者被销毁后进程就成为了
空进程,很容易被系统杀掉;
d. 耗时的较长的工作最好放在服务中完成;


4、Android引入广播机制的用意
a. 从 MVC的角度考虑(应用程序内) 其实回答这个问题的时候还可以这样问,android 为什么要有
那 4大组件,现在的移动开发模型基本上也是照搬的web 那一套 MVC架构,只不过是改了点
嫁妆而已。android 的四大组件本质上就是为了实现移动或者说嵌入式设备上的 MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组
件的信息和数据交互。
b. 程序间互通消息(例如在自己的应用程序内监听系统来电)
c. 效率上(参考UDP的广播协议在局域网的方便性)
d. 设计模式上(反转控制的一种应用,类似监听者模式)


四、 ContentProvider
1、请介绍下 ContentProvider 是如何实现数据共享的
在 Android 中如果想将自己应用的数据(一般多为数据库中的数据)提供给第三发应用,那么
我们只能通过ContentProvider来实现了。
ContentProvider 是应用程序之间共享数据的接口。使用的时候首先自定义一个类继承
ContentProvider,然后覆写 query、insert、update、delete 等方法。因为其是四大组件之一因
此必须在AndroidManifest文件中进行注册。
把自己的数据通过uri的形式共享出去
android 系统下 不同程序 数据默认是不能共享访问
需要去实现一个类去继承ContentProvider
public class PersonContentProvider extends ContentProvider{
public boolean onCreate(){
}
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
}
<provider
android:exported="true"
android:name="com.itheima.contenProvider.provider.PersonContentPro
vider"android:authorities="com.itheima.person" />
第三方可以通过ContentResolver来访问该 Provider。


2、请介绍下 Android 的数据存储方式
a. File存储
b. SharedPreference存储
c. ContentProvider存储
d. SQLiteDataBase 存储
e. 网络存储


3、为什么要用 ContentProvider?它和sql 的实现上有什么差别?
ContentProvider 屏蔽了数据存储的细节,内部实现对用户完全透明,用户只需要关心操作数据的
uri就可以了,ContentProvider可以实现不同app 之间共享。
Sql也有增删改查的方法,但是 sql 只能查询本应用下的数据库。而 ContentProvider 还可
以去增删改查本地文件. xml 文件的读取等。


4、说说 ContentProvider、ContentResolver、ContentObserver 之间的关系
a. ContentProvider 内容提供者,用于对外提供数据
b. ContentResolver.notifyChange(uri)发出消息
c. ContentResolver 内容解析者,用于获取内容提供者提供的数据
d. ContentObserver 内容监听器,可以监听数据的改变状态传智播客武汉校区就业部出品 务实、创新、质量、分享、专注、责任
26
e. ContentResolver.registerContentObserver()监听消息。


五、 ListView
1、ListView 如何提高其效率?
当 convertView 为空时,用 setTag()方法为每个 View 绑定一个存放控件的 ViewHolder 对象。当
convertView不为空, 重复利用已经创建的view的时候, 使用getTag()方法获取绑定的ViewHolder
对象,这样就避免了findViewById对控件的层层查询,而是快速定位到控件。
① 复用ConvertView,使用历史的view,提升效率200%
② 自定义静态类ViewHolder,减少findViewById 的次数。提升效率50%
③ 异步加载数据,分页加载数据。
④ 使用WeakRefrence引用ImageView对象


2、当 ListView 数据集改变后,如何更新 ListView
使用该ListView的 adapter的 notifyDataSetChanged()方法。 该方法会使 ListView 重新绘制。


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


4、ListView 可以显示多种类型的条目吗
这个当然可以的,ListView 显示的每个条目都是通过 baseAdapter 的 getView(int position,
View convertView, ViewGroup parent)来展示的, 理论上我们完全可以让每个条目都是不同类型的
view。
比如:从服务器拿回一个标识为id=1,那么当 id=1 的时候,我们就加载类型一的条目,当 id=2
的时候,加载类型二的条目。常见布局在资讯类客户端中可以经常看到。
除此之外 adapter还提供了 getViewTypeCount()和 getItemViewType(int position)两个方
法。在 getView方法中我们可以根据不同的viewtype 加载不同的布局文件。


5、ListView 如何定位到指定位置
可以通过ListView提供的 lv.setSelection(listView.getPosition());方法。


6、如何在 ScrollView 中如何嵌入 ListView
通常情况下我们不会在 ScrollView 中嵌套 ListView,但是如果面试官非让我嵌套的话也是可以
的。
在ScrollView 添加一个ListView 会导致 listview 控件显示不全,通常只会显示一条,这是因为两个控件的滚动事件冲突导致。所以需要通过listview 中的 item数量去计算 listview 的显示高度,
从而使其完整展示,如下提供一个方法供大家参考。
lv = (ListView) findViewById(R.id.lv);
adapter = new MyAdapter();
lv.setAdapter(adapter);
setListViewHeightBasedOnChildren(lv);
----------------------------------------------------
public void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() *
(listAdapter.getCount() - 1));
params.height += 5;// if without this statement,the listview will be a
// little short
listView.setLayoutParams(params);
}
现阶段最好的处理的方式是: 自定义 ListView,重载 onMeasure()方法,设置全部显示。传智播客武汉校区就业部出品 务实、创新、质量、分享、专注、责任
29
package com.meiya.ui;
import android.widget.ListView;
/**
*
* @Description: scrollview 中内嵌listview 的简单实现
*
* @File: ScrollViewWithListView.java
*
*
* @Version
*/
public class ScrollViewWithListView extends ListView {
public ScrollViewWithListView(android.content.Context context,
android.util.AttributeSet attrs) {
super(context, attrs);
}
/**
* Integer.MAX_VALUE >> 2,如果不设置,系统默认设置是显示两条
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}


7、ListView 中如何优化图片
图片的优化策略比较多。
1、处理图片的方式:
如果ListView中自定义的 Item中有涉及到大量图片的,一定要对图片进行细心的处理,因为图片占的内存是ListView项中最头疼的,处理图片的方法大致有以下几种:
①、不要直接拿路径就去循环 BitmapFactory.decodeFile;使用 Options保存图片大小、不要加
载图片到内存去。
②、对图片一定要经过边界压缩尤其是比较大的图片,如果你的图片是后台服务器处理好的那就
不需要了
③、在 ListView 中取图片时也不要直接拿个路径去取图片,而是以 WeakReference(使用
WeakReference 代替强引用。比如可以使用 WeakReference mContextRef)、SoftReference、
WeakHashMap 等的来存储图片信息。
④、在 getView中做图片转换时,产生的中间变量一定及时释放
2、异步加载图片基本思想:
1)、 先从内存缓存中获取图片显示(内存缓冲)
2)、获取不到的话从 SD卡里获取(SD卡缓冲)
3)、都获取不到的话从网络下载图片并保存到 SD 卡同时加入内存并显示(视情况看是否要显
示)
原理:
优化一:先从内存中加载,没有则开启线程从 SD卡或网络中获取,这里注意从 SD 卡获取图片
是放在子线程里执行的,否则快速滑屏的话会不够流畅。
优化二:于此同时,在 adapter里有个 busy 变量,表示 listview 是否处于滑动状态,如果是滑
动状态则仅从内存中获取图片,没有的话无需再开启线程去外存或网络获取图片。
优化三:ImageLoader 里的线程使用了线程池,从而避免了过多线程频繁创建和销毁,如果每
次总是 new一个线程去执行这是非常不可取的,好一点的用的 AsyncTask类,其实内部也是用到了
线程池。在从网络获取图片时,先是将其保存到sd 卡,然后再加载到内存,这么做的好处是在加载到内存时可以做个压缩处理,以减少图片所占内存。


8、ListView 中图片错位的问题是如何产生的
图片错位问题的本质源于我们的listview使用了缓存convertView, 假设一种场景, 一个listview
一屏显示九个item,那么在拉出第十个item 的时候,事实上该 item 是重复使用了第一个 item,也
就是说在第一个 item 从网络中下载图片并最终要显示的时候,其实该 item 已经不在当前显示区域
内了,此时显示的后果将可能在第十个 item上输出图像,这就导致了图片错位的问题。所以解决之
道在于可见则显示,不可见则不显示。
9、如何刷新 ListView 中单个 item 的数据,不刷新整个 ListView 的数
据?
修改单个Item的数据,然后调用适配器的 notifyDataSetChanged()方法


六、Intent
1、Intent 传递数据时,可以传递哪些类型数据?
Intent可以传递的数据类型非常的丰富, java的基本数据类型和 String以及他们的数组形式
都可以,除此之外还可以传递实现了Serializable和 Parcelable接口的对象。


2、Serializable 和Parcelable 的区别
在使用内存的时候,Parcelable 类比 Serializable 性能高,所以推荐使用 Parcelable类。
1.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。传智播客武汉校区就业部出品 务实、创新、质量、分享、专注、责任
32
2.Parcelable 不能使用在要将数据存储在磁盘上的情况。尽管 Serializable 效率低点,但在这
种情况下,还是建议你用Serializable 。
实现:
1.Serializable 的实现,只需要继承 Serializable 即可。这只是给对象打了一个标记,系统会
自动将其序列化。
2.Parcelabel 的实现,需要在类中添加一个静态成员变量 CREATOR,这个变量需要继承
Parcelable.Creator 接口。
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}


3、请描述一下 Intent 和 IntentFilter
Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的
地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内
容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。
通过Intent 可以实现各种系统组件的调用与激活.
IntentFilter: 可以理解为邮局或者是一个信笺的分拣系统…
这个分拣系统通过3个参数来识别
Action: 动作 view
Data: 数据 uri uri
Category : 而外的附加信息
Action 匹配
Action 是一个用户定义的字符串, 用于描述一个 Android 应用程序组件, 一个 IntentFilter 可
以包含多个 Action。在 AndroidManifest.xml 的 Activity 定义时可以在其 <intent-filter >节点
指定一个 Action 列表用于标示 Activity 所能接受的“动作”,例如:
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<action android:name="cn.itheima.action" />
……
</intent-filter>
如果我们在启动一个 Activity 时使用这样的 Intent 对象:
Intent intent =new Intent();
intent.setAction("cn.itheima.action");
那么所有的 Action 列表中包含了“cn.itheima”的 Activity 都将会匹配成功。
Android 预定义了一系列的 Action 分别表示特定的系统动作。这些 Action 通过常量的方式
定义在 android.content. Intent中,以“ACTION_”开头。我们可以在 Android 提供的文档中找
到它们的详细说明。
URI 数据匹配
一个 Intent 可以通过 URI 携带外部数据给目标组件。在 <intent-filter >节点中,通过
<data/>节点匹配外部数据。
mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定
数据的位置、端口、和路径。如下:
<data android:mimeType="mimeType" android:scheme="scheme"
android:host="host" android:port="port" android:path="path"/>
电话的uri tel: 12345
http://www.baidu.com
自己定义的 uri itcast://cn.itcast/person/10
如果在 Intent Filter 中指定了这些属性, 那么只有所有的属性都匹配成功时 URI 数据匹配才会
成功。
Category 类别匹配
<intent-filter >节点中可以为组件定义一个 Category 类别列表,当 Intent 中包含这个列表
的所有项目时 Category 类别匹配才会成功。


七、Fragment
1、Fragment 跟 Activity 之间是如何传值的
当 Fragment 跟 Activity 绑定之后,在 Fragment 中可以直接通过 getActivity()方法获取到
其绑定的Activity 对象,这样就可以调用Activity 的方法了。在 Activity 中可以通过如下方法获取到
Fragment实例
FragmentManager fragmentManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
Fragment fragment = fragmentManager.findFragmentById(id);
获取到 Fragment之后就可以调用Fragment的方法。也就实现了通信功能。


2、描述一下 Fragment 的生命周期


3、Fragment 的 replace 和 add方法的区别
Fragment本身并没有replace和add方法, 这里的理解应该为使用FragmentManager的replace
和 add 两种方法切换Fragment时有什么不同。
我们经常使用的一个架构就是通过 RadioGroup 切换 Fragment,每个 Fragment 就是一个功能模块。
case R.id.rb_1:
rb_1.setBackgroundColor(Color.RED);
transaction.show(fragment1);
// transaction.replace(R.id.fl, fragment1, "Fragment1");
break;
case R.id.rb_2:
rb_2.setBackgroundColor(Color.YELLOW);
// transaction.replace(R.id.fl, fragment2, "Fragment2");
transaction.show(fragment2);
break;
case R.id.rb_3:
rb_3.setBackgroundColor(Color.BLUE);
// transaction.replace(R.id.fl, fragment3, "Fragment3");
transaction.show(fragment3);
break;
实现这个功能可以通过replace 和 add 两种方法。
Fragment 的容器一个 FrameLayout,add 的时候是把所有的 Fragment 一层一层的叠加到了
FrameLayout上了, 而replace的话首先将该容器中的其他Fragment去除掉然后将当前Fragment
添加到容器中。
一个 Fragment 容器中只能添加一个 Fragment 种类,如果多次添加则会报异常,导致程序终止,
而 replace 则无所谓,随便切换。
因为通过 add 的方法添加的 Fragment,每个 Fragment 只能添加一次,因此如果要想达到切换效
果需要通过 Fragment 的的 hide 和 show 方法结合者使用。将要显示的 show 出来,将其他 hide
起来。这个过程Fragment的生命周期没有变化。
通过 replace 切换 Fragment,每次都会执行上一个 Fragment 的 onDestroyView,新 Fragment
的 onCreateView、onStart、onResume 方法。
基于以上不同的特点我们在使用的使用一定要结合着生命周期操作我们的视图和数据。


4、Fragment 如何实现类似 Activity 栈的压栈和出栈效果的?
Fragment 的事物管理器内部维持了一个双向链表结构,该结构可以记录我们每次 add 的
Fragment和 replace 的 Fragment, 然后当我们点击 back 按钮的时候会自动帮我们实现退栈操作。
Add this transaction to the back stack. This means that the transaction will be remembered after it is committed,
and will reverse its operation when later popped off the stack.
Parameters:
name An optional name for this back stack state, or null.
transaction.addToBackStack("name");
//实现源码 在 BackStackRecord 中
public FragmentTransaction addToBackStack(String name) {
if (!mAllowAddToBackStack) {
throw new IllegalStateException(
"This FragmentTransaction is not allowed to be added to the back
stack.");
}
mAddToBackStack = true;
mName = name;
return this;
}
//上面的源码仅仅做了一个标记
除此之外因为我们要使用FragmentManger用的是FragmentActivity, 因此FragmentActivity
的 onBackPress方法必定重新覆写了。打开看一下,发现确实如此。
/**
* Take care of popping the fragment back stack or finishing the activity
* as appropriate.
*/
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
//mFragments 的原型是 FragmentManagerImpl,看看这个方法都干嘛了
@Override
public boolean popBackStackImmediate() {
checkStateLoss();
executePendingTransactions();
return popBackStackState(mActivity.mHandler, null, -1, 0);
}
//看看 popBackStackState 方法都干了啥,其实通过名称也能大概了解 只给几个片段吧,代码太多

while (index >= 0) {
//从后退栈中取出当前记录对象
BackStackRecord bss = mBackStack.get(index);
if (name != null && name.equals(bss.getName())) {
break;
}
if (id >= 0 && id == bss.mIndex) {
break;
}
index--;
}


5、Fragment 在你们项目中的使用
Fragment 是 android3.0 以后引入的的概念,做局部内容更新更方便,原来为了到达这一点要
把多个布局放到一个 activity 里面,现在可以用多 Fragment 来代替,只有在需要的时候才加载Fragment,提高性能。
Fragment的好处:
(1)Fragment 可以使你能够将 activity 分离成多个可重用的组件,每个都有它自己的生命周期和
UI。
(2)Fragment可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电
脑。
(3)Fragment是一个独立的模块,紧紧地与 activity 绑定在一起。可以运行中动态地移除、加入、
交换等。
(4)Fragment提供一个新的方式让你在不同的安卓设备上统一你的UI。
(5)Fragment 解决 Activity 间的切换不流畅,轻量切换。
(6)Fragment 替代 TabActivity 做导航,性能更好。
(7)Fragment 在 4.2.版本中新增嵌套fragment使用方法,能够生成更好的界面效果。


6、如何切换 fragement,不重新实例化
翻看了 Android 官方 Doc,和一些组件的源代码,发现 replace()这个方法只是在上一个 Fragment
不再需要时采用的简便方法.
正确的切换方式是 add(),切换时hide(),add()另一个 Fragment;再次切换时,只需hide()当前,
show()另一个。
这样就能做到多个Fragment切换不重新实例化:
public void switchContent(Fragment from, Fragment to) {
if (mContent != to) {
mContent = to;
FragmentTransaction transaction
=mFragmentMan.beginTransaction().setCustomAnimations(android.R.anim.fad
e_in, R.anim.slide_out);
if (!to.isAdded()) { // 先判断是否被add 过
transaction.hide(from).add(R.id.content_frame, to).commit(); // 隐藏
当前的 fragment,add下一个到Activity中
} else {
transaction.hide(from).show(to).commit(); // 隐藏当前的
fragment,显示下一个
}
}
}
}

 

 

1:Android中五种数据存储方式分别是什么?他们的特点?



(1)SharedPreference,存放较少的五种类型的数据,只能在同一个包内使
            用,生成XML的格式存放在设备中
(2) SQLite数据库,存放各种数据,是一个轻量级的嵌入式数据库
(3) File文件,通过读取写入方式生成文件存放数据
(4) ContentProvider,主要用于让其他应用程序使用保存的数据
(5) 通过网络获取数据和写入数据到网络存储空间


        答:Android提供了五种存取数据的方式


2:说说 android 中 mvc 的具体体现


mvc是model,view,controller的缩写,mvc包含三个部分:
模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相关事件,交给m层处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:
(1)视图(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入。
(2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写过多的代码,要通过activity交割model业务逻辑层处理,这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
(3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。


3:简述SharedPreferences存储方式以及SharedPreferences与SQLite数据库的区别


SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/<包名>/shared_prefs目录下。SharedPreferences对象本身只能读取数据而不支持写入数据,存储修改是通过Editor对象实现。SharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。



4:描述handler 机制的原理


andriod提供了 Handler 和 Looper 来满足线程间的通信。
Handler 先进先出原则。
Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。 
(1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。 
(2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。 
(3) Message Queue(消息队列):用来存放线程放入的消息。 
(4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
 

 
5:显式intent和隐式intent的区别是什么(android)


答:Intent定义:Intent是一种在不同组件之间传递的请求消息,是应用程序发出的请求和意图。作为一个完整的消息传递机制,Intent不仅需要发送端,还需要接收端。
显式Intent定义:对于明确指出了目标组件名称的Intent,我们称之为显式Intent。
隐式Intent定义:对于没有明确指出目标组件名称的Intent,则称之为隐式Intent。
说明:Android系统使用IntentFilter 来寻找与隐式Intent相关的对象。


6:如何优化ListView


1、如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中尽可能少创建view。
2、给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到图像数据异步加载的效果。
3、如果listview需要显示的item很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候再去加载接下来的20条。


7:简述通过contentResolver获取ContentProvider内容的基本步骤


第一:得到ContentResolver类对象:ContentResolver cr = getContentResolver();
第二:定义要查询的字段String数组。
第三:使用cr.query();返回一个Cursor对象。
第四:使用while循环得到Cursor里面的内容。


8:描述4 种 activity 的启动模式


(1)standard :系统的默认模式,一次跳转即会生成一个新的实例。假设有一个activity命名为MainActivity,执行语句:
startActivity(new Intent(MainActivity.this, MainActivity.class))后,MainActivity将跳转到另外一个MainActivity,也就是现在的Task栈里面有MainActivity的两个实例。按返回键后你会发现仍然是在MainActivity(第一个)里面。
(2)singleTop:singleTop 跟standard 模式比较类似。如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,而只是调用Activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。例:当MainActivity为 singleTop 模式时,执行跳转后栈里面依旧只有一个实例,如果现在按返回键程序将直接退出。
(3)singleTask: singleTask模式和后面的singleInstance模式都是只创建一个实例的。在这种模式下,无论跳转的对象是不是位于栈顶的activity,程序都不会生成一个新的实例(当然前提是栈里面已经有这个实例)。这种模式相当有用,在以后的多activity开发中,经常会因为跳转的关系导致同个页面生成多个实例,这个在用户体验上始终有点不好,而如果你将对应的activity声明为 singleTask 模式,这种问题将不复存在。
(4)singleInstance: 设置为 singleInstance 模式的 activity 将独占一个task(感觉task可以理解为进程),独占一个task的activity与其说是activity,倒不如说是一个应用,这个应用与其他activity是独立的,它有自己的上下文activity。


9:Android中如何访问自定义ContentProvider?


通过ContentProvider的Uri访问开放的数据。
(1)ContenResolver对象通过Context提供的方法getContenResolver()来获得。
(2)ContenResolver提供了以下方法来操作:insert  delete  update  query这些方法分别会调用ContenProvider中与之对应的方法并得到返回的结果。

10:android中的动画有哪几类,它们的特点和区别是什么?


答:Android中动画可以分为两大类:帧动画、补间动画
(1)补间动画:你定义一个开始和结束,中间的部分由程序运算得到。主要有:旋转、平移、放缩和渐变;AlphaAnimation(渐变型动画)、scaleAnimation(缩放型动画)、TranslateAnimation(平移型动画)、 RotateAnimation(旋转型动画)、

(2)逐帧动画:Frame(把一连串的图片进行系列化连续播放,如同放电影的效果),它是通过播放一张一张图片来达到动画的效果;

初级Android开发面试题以及答案: 1. 什么是ActivityActivityAndroid应用程序中的一个组件,它提供了一个用户界面,用户可以与之交互。每个Activity都有一个窗口,用于显示应用程序的用户界面。 2. 什么是Intent? Intent是Android应用程序中的一个组件,它用于在不同的组件之间传递数据和启动其他组件。例如,可以使用Intent启动一个Activity或者启动一个Service。 3. 什么是Service? Service是Android应用程序中的一个组件,它用于在后台执行长时间运行的任务,例如下载文件或者播放音乐。 4. 什么是BroadcastReceiver? BroadcastReceiver是Android应用程序中的一个组件,它用于接收系统或应用程序发出的广播消息。例如,可以使用BroadcastReceiver接收来电或者短信的通知。 5. 什么是ContentProvider? ContentProvider是Android应用程序中的一个组件,它用于管理应用程序的数据。例如,可以使用ContentProvider来管理应用程序的联系人或者日历数据。 6. 什么是布局文件? 布局文件Android应用程序中的一个组件,它用于定义应用程序的用户界面。例如,可以使用布局文件定义一个Activity的界面布局。 7. 什么是资源文件? 资源文件Android应用程序中的一个组件,它用于存储应用程序的各种资源,例如图片、音频、视频等。资源文件可以在应用程序中被引用和使用。 8. 什么是AndroidManifest.xml文件AndroidManifest.xml文件Android应用程序中的一个组件,它用于定义应用程序的各种属性和权限。例如,可以使用AndroidManifest.xml文件定义应用程序的名称、图标、本号等信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值