面试准备:
1.多线程下载原理;
1.因为要多线程下载,要随机去指定位置,用一个randomAccessFile的流
1.请求服务器, 在本地创建一个大小跟服务器一样的文件
RandomAccessFile raf = new RandomAccessFile()
raf.setLength(length);
2.计算每个线程下载的位置.
blockSize = length / threadCount;
int startIndex = (i - 1) * blockSize;
int endIndex = i * blockSize - 1;
3.开启线程分别下载服务器上对应部分的资源(使用range字段),把下载下来的资源放在对应
的本地的文章上
conn.setRequestProperty("Range", "bytes=" + startIndex + "-
+ endIndex);
raf.seek(startIndex);
2.说说你对面向对象的理解:结合项目说
3.设计模式 单例 模板 装饰 观察者 工厂
被观察者继承observable,复写haschange()方法,notifyObserver()
观察者实现observer,回调update()方法;
4.handler机制
handler使用步骤:
* 1.looper.preapere(); 只能执行一次
/**
* 1.获取looper; mLooper = Looper.myLooper();
* 2.获取loooper的messagequeue mQueue =
mLooper.mQueue;
*/
* 2.创建handler.使用handler
new handler();
/**
* 拿到消息队列的引用 发消息发到消息队列里
并给消息排序
* enqueueMessage(queue, msg, uptimeMillis);
* 消息队列中boolean enqueueMessage(Message
msg, long when) {
*/
handler.sendEmptyMessage(0);
* 3.loop.loop();
/**
* 1.msg.target.dispatchMessage(msg);
* 2.handlemessage
*/
5.监听机制;
答:1.定义一个借口 2.声明一个setOnXXlistener方法;3.响应接口里的方法;4.调用
setOnXXlistener的方法
6.wait sleep区别;
wait所属是对象,sleep是Thread
wait释放锁,释放cpu资源
sleep不释放锁,不释放cpu资源
7.线程与进程的区别;
进程:正在运行中的程序,
线程:一个进程至少有一个线程(主线程),线程是程序的一条执行路径;
如:请求网络比较耗时,放在子线程,避免主线程堵塞;anr异常
11.接口与抽象类的区别;
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象
的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认
即为public abstract类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任
意,但接口中定义的变量只能是public static final类型,并且默认即为public static
final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。
应用:模板设计 父类方法中间的某段代码不确定,留给子类干,就用模板方法设计模式
自己理解:
抽象类主要用于对类中共性的抽取,比如模板设计方法
接口主要是自定义接口
14.activity fragemtn service 生命周期;
activity:oncreate onstart ouresume onpause onstop ondestory
?HOME键的执行顺序:onPause->onSaveInstanceState->onStop->onRestart->onStart-
>onResume
?BACK键的顺序: onPause->onStop->onDestroy->onCreate->onStart->onResume
A--->B :A的生命周期:onpause->onSaveInstanceState->onstop->onrestart->onStart-
>onResume
四种启动模式:standard
singTop:如果启动的activity在当前任务栈栈顶中,就不创建新的activity方法,而是调用原
来实例的onNewIntend();
如:添加浏览器书签
singleTask:只有一个实例,如果要激活的activity在任务栈中,就复用,调用onnewIntent方
法,
因为有些activity创建一次开销比较大,不如浏览器内核打开一个浏览器;browseractiity;
singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个
实例,不允许有别的Activity存在单独开一个任务栈;而且整个手机里只用一个activity实
例存在
如:呼叫界面:
service:
(1)startservice:
oncreate onstartcommand ondestory
(2)bindService:
oncreate onbind onUnbind ondestory
(3)混合生命周期
oncrate onstartcommand onbind onunbind ondestory
fragment:
onattatch oncreate oncreateview onactivitycreate onstart onresume
onpause onstop ondestoryView ondestory ondatach
13:内部类:
外部类可以访问内部类,但需要建立内部类对象
内部类在成员变量位置上,在外部其他类访问内部类非静态方法,且修饰符为默认
Outer.Inner inner = new Outer().new Inner();
inner.function();
如果为static
new Outer.Inner().functin();
如果访问内部类静态成员
Outer.Inner().function();
匿名内部类是因为方法总要调用,所以把内部类的定义,和调用简写了
12.数据库语句
13.集合和流的理解
8.自定义控件
/*
* view 对象显示的屏幕上,有几个重要步骤:
* 1、构造方法 创建 对象。
* 2、测量view的大小。 onMeasure(int,int);(空间渲染的过程必须测量)
* 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。
onLayout();
* 4、绘制 view 的内容 。 onDraw(Canvas)
*/
9.事件分发
viewgroup事件分发与消费:
首先自上而下分发,如果不消费,就往上传,看dispatcheventtouch方法的返回值结果,
如果是false,继续往上返回,
view的事件消费 :
imageView事件处理为例:
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
setOntouchvent中ontouch返回为true,所有事件都消费,
如果为false,只响应action_down;
//点击事件的调用方式,就是回调方法
performClick();
public boolean performClick() {
....
if (mOnClickListener != null) {
...
//回调onclick方法
mOnClickListener.onClick(this);
...
}
...
}
点击事件和touch事件冲突解决:
ontouch返回true,onclick不会响应;
ontouch返回发了,onclick才会响应;
9.listview的优化
1.条目复用;避免内容溢出
2.保存孩子节点的id
避免多次遍历寻找孩子,提高效率,利用viewhodler
3.复杂条目的写法
复写两个方法
getViewTypeCount();
getItemViewType();
10.三级缓存
1.先从内存中取,没有再从文件中去,没有,从网络中取,
利用线程池,获取一个线程请求网络,并写入内存和文件中
再次进入时,就可以从内存中去,没有再从文件中取,
public ImageCacheUtil(Context context,Handler handler) {
int maxSize = (int) (Runtime.getRuntime().maxMemory()/8);
lruCache = new LruCache
@Override
protected int sizeOf(String key, Bitmap value) {
//getRowBytes()一行上面对应像素点占用的大小
*value.getHeight()行号
return value.getRowBytes()*value.getHeight();
}
};
cacheDir = context.getCacheDir();
//2*cup核数+1
newFixedThreadPool = Executors.newFixedThreadPool(5);
this.handler = handler;
}
public Bitmap getBitmap(String imgUrl,int position){
//position为确认给那个imageview控件使用的tag
Bitmap bitmap = null;
//1,内存中去取
bitmap = lruCache.get(imgUrl);
if(bitmap!=null){
Log.i(tag, "从内存中获取到的图片");
return bitmap;
}
//2,文件中去取
bitmap = getBitmapFromLocal(imgUrl);
if(bitmap!=null){
Log.i(tag, "从文件中获取到的图片");
return bitmap;
}
//3,网络去下载
getBitmapFromNet(imgUrl,position);
Log.i(tag, "网络获取到的图片.......");
return null;
}
class RunnableTask implements Runnable{
private String imageUrl;
private int position;
public RunnableTask(String imageUrl,int position) {
this.imageUrl = imageUrl;
this.position = position;
}
@Override
public void run() {
//访问网络,下载图片
try {
URL url = new URL(imageUrl);
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
//读取超时时间()
connection.setReadTimeout(5000);
//链接超时时间()
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
InputStream inputStream =
connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream
(inputStream);
//消息机制()
Message msg = new Message();
msg.what = SUCCESS;
msg.obj = bitmap;
msg.arg1 = position;
handler.sendMessage(msg);
//内存缓存
lruCache.put(imageUrl, bitmap);
//写入文件
writeToLocal(imageUrl, bitmap);
return ;
} catch (Exception e) {
e.printStackTrace();
}
Message msg = new Message();
msg.what = FAIL;
handler.sendMessage(msg);
}
}
private void writeToLocal(String imageUrl, Bitmap bitmap) {
String fileName;
try {
fileName = MD5Encoder.encode(imageUrl).substring(10);
File file = new File(cacheDir,fileName);
FileOutputStream fileOutputStream = new
FileOutputStream(file.getAbsolutePath());
//1,定义一个大小如果超过当前大小的时候,就需要进行等比例
压缩
bitmap.compress(CompressFormat.JPEG, 100,
fileOutputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
private void getBitmapFromNet(String url,int position) {
newFixedThreadPool.execute(new RunnableTask(url,position));
}
private Bitmap getBitmapFromLocal(String imgUrl) {
String fileName;
try {
fileName = MD5Encoder.encode(imgUrl).substring(10);
File file = new File(cacheDir,fileName);
Bitmap bitmap = BitmapFactory.decodeFile
(file.getAbsolutePath());
//加入到内存中去(内存的效率要高)
lruCache.put(imgUrl, bitmap);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
图片错乱问题:
1.复用产生的问题:
解决:holder.imageview.settag(position);
if(bitmap!=null&&(Integer)holder.image.getTag()==position){
holder.image.setImageBitmap(bitmap);
}
11.介绍Android中的动画
1.view animation(平移,旋转等),drawable animation(帧动画),property animation(插值
器的使用,加入一些算法)
12.反射的原理:就是把Java类中的各种成分映射成相应的java类,(对类的解剖);
要想对一个类进行内容的获取,必须要先获得该字节码文件的对象
该对象类型是Class类型
Class class{
Filed filed;//字段
Method method;//构造函数
Contructor constructor;//构造函数
按照面向对象将字段,方法,构造器都封装成了对象;
}
13.java中内存的分析:(面试时画个图解释更好)
1.寄存器,cpu涉及的区域
2.本地方法区,是和系统相关的代码存储区域
3.栈内存 存储局部变量,变量运算区域一结束,就释放
4.堆内存 存储的是数组和对象,简单说,堆内存存储的都是实体(能存储很多数据的地方就是
实体)
new出来的都存放在堆内存
5.方法区 存储函数的地方(或者说存储共享数据的地方)
14:imageLoader的理解以及它和其他的类似的图片加载有什么不同?
1.里面的防止内存溢出的算法,如果超过limit,就遍历吧集合中的图片删掉,
还有lruCache用的是linkedHashedmap集合,去remove,get;
2.如果图片很大,超过limit时,就压缩,用一个永真循环,去动态改变压缩比例的因子;
15.gallery用过吗:
和listview类似,使用适配器,填充图片即可;
16.adapter作用和常用的那些adapter;
作用:为容器提供子视图,利用视图的数据和view来构建每个子视图。
arrayAdapter ,simpleCursorAdapter, cursorAdapter resourceCursorAdapter
16.intent,service,activity的区别
1.Intent: Intent的调用是用来进行UI之间的切换的,封装了动作和动作对应的数据;
2.Service:服务,具有一段较长生命周期且没有用户界面的程序。Service在后台运行,不
可交互,不能自己运行,需要通过Activity或者其他Context对象来调用,有
Context.startService()和Context.bindService()两种方式启动. Service的生命周期:
onCreate、onStart、onDestroy
3.activity:是最基本的android应用程序组件,主要是生命周期的把握,其次就是状态的保
存和恢复(onSaveInstanceState onRestoreInstanceState),以及Activity之间的跳转和
数据传输(intent)。
context:应用程序所有功能可以通过他访问;
17.垃圾回收机制:
18. Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?
DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立
的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个
概念。
19、说说mvc模式的原理,它在android中的运用
MVC(Model_view_contraller)”模型_视图_控制器”。 MVC应用程序总是由这三个部分组成
。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要 Controller改
变了Models的数据或者属性,所有依赖的View都会自动更新。类似的,只要Controller改变
了View,View会 从潜在的Model中获取数据来刷新自己。
20.2. GC内存泄露?
出现情况:?
1.数据库的cursor没有关闭?
2.构造adapter时,没有使用缓存contentview?
?? 衍生listview的优化问题-----减少创建view的对象,充分使用contentview,可以使用一
静态类来优化处理getview的过程/?
3.Bitmap对象不使用时采用recycle()释放内存?
4.activity中的对象的生命周期大于activity?
不要保留对Context-Activity长时间的引用(对Activity的引用的时候,必须确保拥有和
Activity一样的生命周期)
尝试使用Context-Application来替代Context-Activity
如果你不想控制内部类的生命周期,应避免在Activity中使用非静态的内部类,而应该
使用静态的内部类,并在其中创建一个对Activity的弱引用。这种情况的解决办法是使用一
个静态的内部类,其中拥有对外部类的WeakReference,如同ViewRoot和它的Winner类那样
另外:内存泄露与内存溢出的区别:
内存溢出:指的是申请的内存不够,
内存泄露:指的是申请内存后,对某些资源没有及时释放,很多内存泄露,最终会导致内存溢出
;
21.IPC及原理
Linux系统中进程间通信的方式有:socket, named pipe,message queque, signal,share
memory。Java系统中的进程间通信方式有socket, named pipe等
IBinder接口
IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被
其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远
程对象,调用者不需要关心指向的对象是本地的还是远程。
22.get和post区别:
1.get提交,提交的信息显示在地址栏
post提交,提交的信息不显示在地址栏
2.get提交,对于敏感的数据不安全
post提交,对于敏感的数据安全
3.get提交,对于大数据不行,因为地址栏存储体积有限
post提交,可以提交大体积数据
4.get提交,将信息封装到请求消息的请求行中
post提交,将信息封装到请求体中;
5.服务端区别
出现乱码,先用iso8859编码,在指定中文码表解码,对get和post都有用,但是
但对于post提交的中文,还有一种解决方法,
request.setcharacterencoding(),这种方法只对请求体中的数据有用;
23.状态选择器:
24.自定义属性:
1.添加自定义的属性.
2.声明命名空间
3. 声明自定义的属性 自定义样式 values下新建attrs.xml文件
4.TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.MySettingView);
25:Android保存数据的方法有5种,
sharedperference存储,File文件存储,sqlite数据库存储,contentprovider存储,网络存储,
26.activity之间传递数据的方法有哪些?
1.Intent对象
传输数据仅限简单数据和实现序列话的对象。
2.静态变量
将需要共享的对象或者数据声明为静态,可以传递任何类型的数据
3.剪切板
可以利用Android自带的剪切板功能传送数据
传递数据
Intent intent=new Intent(this,MainActivity.class);
ClipboardManager cliper=(ClipboardManager)getSystemServer
(Context.CLIPBOARD_SERVER);
cliper.setText("message");
startActivity(intent);
接收数据
ClipboardManager cliper=(ClipboardManager)getSystemServer
(Context.CLIPBOARD_SERVER);
String str=cliper.getText().toString();
4.全局对象
为每个应用程序定义一个全局的对象,该对象创建由系统负责,使用全局对象需要继承
android.app.Application类,可以在该类中定义任何方法。
package com.example.transmitdata;
import android.app.Application;
public class mAPP extends Application(){
public String str;
public Data data;
}
然后需要在AndroidManifest.xml文件中定义该类
package="com.example.transmitdata" ...... 面试官问:activity之间传递一个大的图片怎么传: provider 1.简要描述对Static关键字的理解; 2.简要描述java中内存回收机制(gc)的理解; 3.java中线程同步的几种方式; 4.请描述Activity的声明周期; 5.handler机制的原理; 6.简要描述android中view的绘制机制 7.简要描述androdi中事件分发机制: 9.android dvn的进程和linux进程,应用程序进程是否为同一个概念?
/>
/>
可以在程序任意位置获取mAPP对象。
mAPP mapp=(mAPP)getApplicationContext();
只能是用文件把图片存储,再在另一个activity中在获取;
5 基于Ipc的通信机制
context与service之间的传输,如Activity与Service之间的通信
6.基于外部存储的传输 ,File/Preference/Sqlite,如果要针对第三方应用需要Content
Static静态的,随着类的加载而加载,生命周期为进程的生命周期;
同一个类中的static变量在内存中只会有一份,不同对象共享,
static方法相对普通方法调用速度更快,一般工具类的方法都是static
static的调用可以直接用类调用,而不必创建对象;
gc的调用:在内存紧张时,系统会调用gc释放内存并且2.3版本以上gc是异步调用的,也可以手动gc,
gc的原理:系统中有一个GcRoot,gc的时候系统会遍历凡是gcroot可以引用到的均不会被回收,gcroot引用
不到的会被回收,根据这个原理,内存泄漏便是由于长生命周期的对象引用段声明周期的对象导致
短生命周期的无法被回收.
同步方法,与同步锁
同步方法用于在方法上,同步锁要一个对象
线程安全问题:多个线程同事访问一个对象导致数据错乱;
oncreate ,onstart,onresume,onpause,onstop,ondestory,
一般可以在onause或者onstart中做数据刷新的工作;
主要是hander thread,looper,message之间的关系;
messagequeue为消息的存储单元,内部为单链表,用于消息的存储.
looper为消费的执行单元,looper.loop()方法中无限循环取出消息执行消息,
handler为消息的发送单元.
looper.prepare和looper.loop()在哪个线程中最终就在哪个线程中调用handler.handlermessage()方法,
handler拿到哪个线程的looper就会拿到对应线程的messagequeue,然后往相应的messagequeue发送消息,
looper.loop()在哪个线程最终hanldermessage就在哪个线程执行,如handlerthread就是子线程中执行.
onmeasure测量:根据父view传递过来的measurespec和子view的layoutparams形成自己的测量规则测量出自己的大小.
viewgroup会通过measurechild方法一步步从上到下测量出子view的大小.,然后测量出自己的大小,在setmeasuredemension()中设置自身大小;
onlayout布局:setFrame()设置自己的四个顶点坐标,然后调用onlayout测量,设置子view的四个顶点坐标一步步从上到下布局完成;
draw规则:先绘制背景,然后在ondraw中绘制内容,在dispatchDraw中绘制子view最后绘制装饰,dispatchdraw()中完成从上到下的遍历绘制.
从activity,windwo,view
view先判断ontouchlistener是否是null,用ontouch再判断view是否enable如果false则再调用ontouchevent()如果可点击或可长点击则消耗事件.
viewgroup会从最后一个子view开始遍历判断点击坐标是否落在子view区域内和子view是否在做动画如果满足条件调用子view的dispatchtouchevent()
分发成功就把子view设置为target,以后down事件之后的传递都给这个子view,不然调用viewgroup的ontouchenevent()
8.请说出android进程间传递数据的几种方式
intent,bundle,binder,content privder,广播,messager,文件,网络,
是同一个概念,android启动一个进程就会从母进程中fork一个进程,这个fork的进程就是dvm进程就是linux进程.
10.android中一张40x40像素的图片加载后所占用多大的内存;
如果图片是argb8888的4x40x40=6400字节,和每个像素占用的字节数有关;